1 /* 2 * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.openjdk.bench.java.util.stream.pipeline; 26 27 import org.openjdk.jmh.annotations.Benchmark; 28 import org.openjdk.jmh.annotations.BenchmarkMode; 29 import org.openjdk.jmh.annotations.Mode; 30 import org.openjdk.jmh.annotations.OutputTimeUnit; 31 import org.openjdk.jmh.annotations.Param; 32 import org.openjdk.jmh.annotations.Scope; 33 import org.openjdk.jmh.annotations.Setup; 34 import org.openjdk.jmh.annotations.State; 35 36 import java.util.Iterator; 37 import java.util.concurrent.TimeUnit; 38 import java.util.concurrent.atomic.LongAdder; 39 import java.util.function.LongConsumer; 40 import java.util.stream.LongStream; 41 42 /** 43 * Benchmark for forEach()/iterator()/into() operations; 44 * Testing which one is faster for semantically-equvalent operations. 45 */ 46 @BenchmarkMode(Mode.Throughput) 47 @OutputTimeUnit(TimeUnit.SECONDS) 48 @State(Scope.Thread) 49 public class Terminal { 50 51 /** 52 * Implementation notes: 53 * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison 54 * - operations are explicit inner classes to untangle unwanted lambda effects 55 */ 56 57 @Param("100000") 58 private int size; 59 60 private LongAdder sink; 61 private LongConsumer block; 62 63 @Setup 64 public void setup() { 65 sink = new LongAdder(); 66 block = new LongConsumer() { 67 @Override 68 public void accept(long v) { 69 sink.add(v); 70 } 71 }; 72 } 73 74 @Benchmark 75 public long baseline_prim_acc() { 76 long s = 0; 77 for (long l = 0L; l < size; l++) { 78 s += l; 79 } 80 sink.add(s); 81 return sink.sum(); 82 } 83 84 @Benchmark 85 public long baseline_prim_sink() { 86 for (long l = 0L; l < size; l++) { 87 sink.add(l); 88 } 89 return sink.sum(); 90 } 91 92 @Benchmark 93 public long baseline_iterator_acc() { 94 long s = 0; 95 for (Iterator<Long> iterator = LongStream.range(0, size).boxed().iterator(); iterator.hasNext(); ) { 96 Long l = iterator.next(); 97 s += l; 98 } 99 sink.add(s); 100 return sink.sum(); 101 } 102 103 @Benchmark 104 public long baseline_iterator_sink() { 105 for (Iterator<Long> iterator = LongStream.range(0, size).boxed().iterator(); iterator.hasNext(); ) { 106 sink.add(iterator.next()); 107 } 108 return sink.sum(); 109 } 110 111 @Benchmark 112 public long seq_iterator() { 113 Iterator<Long> i = LongStream.range(0, size).boxed().iterator(); 114 while (i.hasNext()) { 115 sink.add(i.next()); 116 } 117 return sink.sum(); 118 } 119 120 @Benchmark 121 public long par_iterator() { 122 Iterator<Long> i = LongStream.range(0, size).parallel().boxed().iterator(); 123 while (i.hasNext()) { 124 sink.add(i.next()); 125 } 126 return sink.sum(); 127 } 128 129 @Benchmark 130 public long seq_forEach() { 131 LongStream.range(1, size).forEach(block); 132 return sink.sum(); 133 } 134 135 @Benchmark 136 public long par_forEach() { 137 LongStream.range(1, size).parallel().forEach(block); 138 return sink.sum(); 139 } 140 141 @Benchmark 142 public long seq_into() { 143 return LongStream.range(1, size) 144 .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); 145 } 146 147 @Benchmark 148 public long par_into() { 149 return LongStream.range(1, size).parallel() 150 .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); 151 } 152 153 }