# HG changeset patch # User redestad # Date 1542293175 -3600 # Thu Nov 15 15:46:15 2018 +0100 # Node ID 15dd749af5b5f348098808ef4790966bb2e886f3 # Parent 2ed42e41e712570d8e917c1ff61bc4f4538818f1 8061282: Migrate jmh-jdk-microbenchmarks into the JDK Reviewed-by: ecaspole, mchung diff --git a/test/micro/classes/org/openjdk/bench/java/io/BlackholedOutputStream.java b/test/micro/classes/org/openjdk/bench/java/io/BlackholedOutputStream.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/BlackholedOutputStream.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.io.OutputStream; + +public class BlackholedOutputStream extends OutputStream { + + private final Blackhole bh; + + public BlackholedOutputStream(Blackhole bh) { + this.bh = bh; + } + + @Override + public void write(int b) throws IOException { + bh.consume(b); + } + + @Override + public void write(byte[] b) throws IOException { + bh.consume(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + bh.consume(b); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/FileChannelRead.java b/test/micro/classes/org/openjdk/bench/java/io/FileChannelRead.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/FileChannelRead.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class FileChannelRead { + + @Param("1000000") + private int fileSize; + + private File f; + private FileChannel fc; + private ByteBuffer bb; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("FileChannelReadBench", ".bin"); + try (FileOutputStream fos = new FileOutputStream(f)) { + for (int i = 0; i < fileSize; i++) { + fos.write((byte) i); + } + } + bb = ByteBuffer.allocate(1); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws IOException { + fc = FileChannel.open(f.toPath(), StandardOpenOption.READ); + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + fc.close(); + } + + @Benchmark + public void test() throws IOException { + int ret = fc.read(bb); + bb.flip(); + if (ret == -1) { + // start over + fc.position(0); + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/FileChannelWrite.java b/test/micro/classes/org/openjdk/bench/java/io/FileChannelWrite.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/FileChannelWrite.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class FileChannelWrite { + + @Param("1000000") + private int fileSize; + + private File f; + private FileChannel fc; + private ByteBuffer bb; + private int count; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("FileChannelWriteBench", ".bin"); + bb = ByteBuffer.allocate(1); + bb.put((byte) 47); + bb.flip(); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws IOException { + fc = FileChannel.open(f.toPath(), StandardOpenOption.WRITE); + count = 0; + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + fc.close(); + } + + @Benchmark + public void test() throws IOException { + fc.write(bb); + bb.flip(); + count++; + if (count >= fileSize) { + // start over + fc.position(0); + count = 0; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/FileRead.java b/test/micro/classes/org/openjdk/bench/java/io/FileRead.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/FileRead.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class FileRead { + + @Param("1000000") + private int fileSize; + + private File f; + private FileInputStream fis; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("FileReadBench", ".bin"); + try (FileOutputStream fos = new FileOutputStream(f)) { + for (int i = 0; i < fileSize; i++) { + fos.write((byte) i); + } + } + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws FileNotFoundException { + fis = new FileInputStream(f); + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + fis.close(); + } + + @Benchmark + public void test() throws IOException { + int ret = fis.read(); + if (ret == -1) { + // start over + fis.close(); + fis = new FileInputStream(f); + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/FileWrite.java b/test/micro/classes/org/openjdk/bench/java/io/FileWrite.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/FileWrite.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class FileWrite { + + @Param("1000000") + private int fileSize; + + private File f; + private FileOutputStream fos; + private long count; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("FileWriteBench", ".bin"); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws FileNotFoundException { + fos = new FileOutputStream(f); + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + fos.close(); + } + + @Benchmark + public void test() throws IOException { + fos.write((byte) count); + count++; + if (count >= fileSize) { + // restart + fos.close(); + fos = new FileOutputStream(f); + count = 0; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/ObjectStreamClasses.java b/test/micro/classes/org/openjdk/bench/java/io/ObjectStreamClasses.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/ObjectStreamClasses.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.concurrent.TimeUnit; + +/** + * A micro benchmark used to measure the performance impact from multi threaded access to ObjectStreamClass. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ObjectStreamClasses { + + public Class[] classes; + + @Setup + public void setup() { + LinkedList queue = new LinkedList(); + int i = 0; + while (true) { + // Loop until we get a ClassNotFoundException + // Maybe rewrite this considering the fact that there are 29 + // inner classes available? + try { + Class clazz = Class.forName(ObjectStreamClasses.class.getName() + "$SerializableClass" + i++); + queue.add(clazz); + } catch (ClassNotFoundException e) { + break; + } + } + classes = new Class[queue.size()]; + + // Make ObjectStreamClass load all classes into the static map + i = 0; + while (!queue.isEmpty()) { + classes[i] = (Class) queue.remove(); + i++; + } + } + + /** + * Tests the static lookup function. Depending on JRE version the internal behavior is different but the general + * behavior is a synchronized call to some sort of static container. + */ + @Benchmark + public void testLookup(Blackhole bh) { + for (Class klass : classes) { + bh.consume(ObjectStreamClass.lookup(klass)); + } + } + + static class SerializableClass0 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass1 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass2 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass3 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass4 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass5 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass6 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass7 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass8 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass9 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass10 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass11 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass12 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass13 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass14 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass15 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass16 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass17 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass18 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass19 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass20 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass21 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass22 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass23 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass24 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass25 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass26 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass27 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass28 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + static class SerializableClass29 extends SerializableClass { + private static final long serialVersionUID = 1L; + } + + @SuppressWarnings("unused") + private static class SerializableClass implements Serializable { + + private static final long serialVersionUID = 6107539118220989250L; + public Object objectField00 = new Object(); + public Object objectField01 = new Object(); + public Object objectField02 = new Object(); + public Object objectField03 = new Object(); + public Object objectField04 = new Object(); + public Object objectField05 = new Object(); + public Object objectField06 = new Object(); + public Object objectField07 = new Object(); + public Object objectField08 = new Object(); + public Object objectField09 = new Object(); + public Object objectField10 = new Object(); + public Object objectField11 = new Object(); + public Object objectField12 = new Object(); + public Object objectField13 = new Object(); + public Object objectField14 = new Object(); + public Object objectField15 = new Object(); + public Object objectField16 = new Object(); + public Object objectField17 = new Object(); + public Object objectField18 = new Object(); + public Object objectField19 = new Object(); + public Object objectField20 = new Object(); + public Object objectField21 = new Object(); + public Object objectField22 = new Object(); + public Object objectField23 = new Object(); + public Object objectField24 = new Object(); + public Object objectField25 = new Object(); + public Object objectField26 = new Object(); + public Object objectField27 = new Object(); + public Object objectField28 = new Object(); + public Object objectField29 = new Object(); + + SerializableClass() { + super(); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/RandomAccessRead.java b/test/micro/classes/org/openjdk/bench/java/io/RandomAccessRead.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/RandomAccessRead.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class RandomAccessRead { + + @Param("1000000") + private int fileSize; + + private RandomAccessFile raf; + private long offset; + private int deltaIndex; + private int[] deltas; + private File f; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("RandomAccessBench", ".bin"); + try (FileOutputStream fos = new FileOutputStream(f)) { + for (int i = 0; i < fileSize; i++) { + fos.write((byte) i); + } + } + deltas = new int[]{1, 2, 3, 5, 7, 11, 13, 17, 19, 23}; + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws IOException { + raf = new RandomAccessFile(f, "rw"); + offset = 0; + deltaIndex = 0; + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + raf.close(); + } + + @Benchmark + public int test() throws IOException { + offset = offset + deltas[deltaIndex]; + if (offset >= fileSize) { + offset = 0; + } + deltaIndex++; + if (deltaIndex >= deltas.length) { + deltaIndex = 0; + } + raf.seek(offset); + return raf.read(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/RandomAccessWrite.java b/test/micro/classes/org/openjdk/bench/java/io/RandomAccessWrite.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/RandomAccessWrite.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on disk subsystem performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class RandomAccessWrite { + + @Param("1000000") + private int fileSize; + + private File f; + private RandomAccessFile raf; + private long offset; + private int deltaIndex; + private int[] deltas; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + f = File.createTempFile("RandomAccessBench", ".bin"); + try (FileOutputStream fos = new FileOutputStream(f)) { + for (int i = 0; i < fileSize; i++) { + fos.write((byte) i); + } + } + deltas = new int[]{1, 2, 3, 5, 7, 11, 13, 17, 19, 23}; + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException { + f.delete(); + } + + @Setup(Level.Iteration) + public void beforeIteration() throws IOException { + raf = new RandomAccessFile(f, "rw"); + offset = 0; + deltaIndex = 0; + } + + @TearDown(Level.Iteration) + public void afterIteration() throws IOException { + raf.close(); + } + + @Benchmark + public void test() throws IOException { + offset = offset + deltas[deltaIndex]; + if (offset >= fileSize) { + offset = 0; + } + deltaIndex++; + if (deltaIndex >= deltas.length) { + deltaIndex = 0; + } + raf.seek(offset); + raf.write((byte) offset); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/SerializationWriteReplace.java b/test/micro/classes/org/openjdk/bench/java/io/SerializationWriteReplace.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/SerializationWriteReplace.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import org.openjdk.bench.java.io.BlackholedOutputStream; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class SerializationWriteReplace { + + private BlackholedOutputStream bos; + private ObjectOutputStream os; + + @Setup + public void setupStreams(Blackhole bh) throws IOException { + bos = new BlackholedOutputStream(bh); + os = new ObjectOutputStream(bos); + } + + @TearDown + public void downStreams() throws IOException { + os.close(); + bos.close(); + os = null; + bos = null; + } + + @Benchmark + public void writeReplace() throws IOException, ClassNotFoundException { + os.writeObject(new Class2()); + } + + public abstract static class Base implements Serializable { + private static final long serialVersionUID = 1L; + } + + public static class Class1 extends Base { + private static final long serialVersionUID = 2L; + } + + public static class Class2 extends Class1 { + private static final long serialVersionUID = 3L; + Object writeReplace() throws ObjectStreamException { + return new Class3(); + } + } + + public static class Class3 extends Base { + private static final long serialVersionUID = 4L; + private String tuto = "tuto"; + private byte b = (byte) 0xff; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/io/UTF8.java b/test/micro/classes/org/openjdk/bench/java/io/UTF8.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/io/UTF8.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.io; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring UTF8 char operations. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class UTF8 { + + private String s; + private BlackholedOutputStream bos; + private DataOutputStream dos; + + @Setup + public void setup(Blackhole bh) { + bos = new BlackholedOutputStream(bh); + dos = new DataOutputStream(bos); + s = "abcdefghijklmnopqrstuvxyz0123456789"; + } + + @Benchmark + public void testCharConversion() throws IOException { + dos.writeUTF(s); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyAligned.java b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyAligned.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyAligned.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring aligned System.arraycopy. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayCopyAligned { + + @Param({"1", "3", "5", "10", "20", "70", "150", "300", "600", "1200"}) + int length; + + int fromPos, toPos; + byte[] fromByteArr, toByteArr; + char[] fromCharArr, toCharArr; + int[] fromIntArr, toIntArr; + long[] fromLongArr, toLongArr; + + @Setup + public void setup() { + // Both positions aligned + fromPos = 8; + toPos = 8; + + fromByteArr = new byte[1210]; + toByteArr = new byte[1210]; + fromCharArr = new char[1210]; + toCharArr = new char[1210]; + fromIntArr = new int[1210]; + toIntArr = new int[1210]; + fromLongArr = new long[1210]; + toLongArr = new long[1210]; + } + + @Benchmark + public void testByte() { + System.arraycopy(fromByteArr, fromPos, toByteArr, toPos, length); + } + + @Benchmark + public void testChar() { + System.arraycopy(fromCharArr, fromPos, toCharArr, toPos, length); + } + + @Benchmark + public void testInt() { + System.arraycopy(fromIntArr, fromPos, toIntArr, toPos, length); + } + + @Benchmark + public void testLong() { + System.arraycopy(fromLongArr, fromPos, toLongArr, toPos, length); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring Unaligned System.arraycopy. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayCopyUnalignedBoth { + + @Param({"1", "3", "5", "10", "20", "70", "150", "300", "600", "1200"}) + int length; + + int fromPos, toPos; + byte[] fromByteArr, toByteArr; + char[] fromCharArr, toCharArr; + int[] fromIntArr, toIntArr; + long[] fromLongArr, toLongArr; + + @Setup + public void setup() { + // Both positions Unaligned + fromPos = 9; + toPos = 10; + + fromByteArr = new byte[1210]; + toByteArr = new byte[1210]; + fromCharArr = new char[1210]; + toCharArr = new char[1210]; + fromIntArr = new int[1210]; + toIntArr = new int[1210]; + fromLongArr = new long[1210]; + toLongArr = new long[1210]; + } + + @Benchmark + public void testByte() { + System.arraycopy(fromByteArr, fromPos, toByteArr, toPos, length); + } + + @Benchmark + public void testChar() { + System.arraycopy(fromCharArr, fromPos, toCharArr, toPos, length); + } + + @Benchmark + public void testInt() { + System.arraycopy(fromIntArr, fromPos, toIntArr, toPos, length); + } + + @Benchmark + public void testLong() { + System.arraycopy(fromLongArr, fromPos, toLongArr, toPos, length); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring Unaligned System.arraycopy. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayCopyUnalignedDst { + + @Param({"1", "3", "5", "10", "20", "70", "150", "300", "600", "1200"}) + int length; + + int fromPos, toPos; + byte[] fromByteArr, toByteArr; + char[] fromCharArr, toCharArr; + int[] fromIntArr, toIntArr; + long[] fromLongArr, toLongArr; + + @Setup + public void setup() { + // Dst position Unaligned + fromPos = 8; + toPos = 9; + + fromByteArr = new byte[1210]; + toByteArr = new byte[1210]; + fromCharArr = new char[1210]; + toCharArr = new char[1210]; + fromIntArr = new int[1210]; + toIntArr = new int[1210]; + fromLongArr = new long[1210]; + toLongArr = new long[1210]; + } + + @Benchmark + public void testByte() { + System.arraycopy(fromByteArr, fromPos, toByteArr, toPos, length); + } + + @Benchmark + public void testChar() { + System.arraycopy(fromCharArr, fromPos, toCharArr, toPos, length); + } + + @Benchmark + public void testInt() { + System.arraycopy(fromIntArr, fromPos, toIntArr, toPos, length); + } + + @Benchmark + public void testLong() { + System.arraycopy(fromLongArr, fromPos, toLongArr, toPos, length); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring Unaligned System.arraycopy. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayCopyUnalignedSrc { + + @Param({"1", "3", "5", "10", "20", "70", "150", "300", "600", "1200"}) + int length; + + int fromPos, toPos; + byte[] fromByteArr, toByteArr; + char[] fromCharArr, toCharArr; + int[] fromIntArr, toIntArr; + long[] fromLongArr, toLongArr; + + @Setup + public void setup() { + // Dst position Unaligned + fromPos = 5; + toPos = 8; + + fromByteArr = new byte[1210]; + toByteArr = new byte[1210]; + fromCharArr = new char[1210]; + toCharArr = new char[1210]; + fromIntArr = new int[1210]; + toIntArr = new int[1210]; + fromLongArr = new long[1210]; + toLongArr = new long[1210]; + } + + @Benchmark + public void testByte() { + System.arraycopy(fromByteArr, fromPos, toByteArr, toPos, length); + } + + @Benchmark + public void testChar() { + System.arraycopy(fromCharArr, fromPos, toCharArr, toPos, length); + } + + @Benchmark + public void testInt() { + System.arraycopy(fromIntArr, fromPos, toIntArr, toPos, length); + } + + @Benchmark + public void testLong() { + System.arraycopy(fromLongArr, fromPos, toLongArr, toPos, length); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ClassForName.java b/test/micro/classes/org/openjdk/bench/java/lang/ClassForName.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ClassForName.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Tests java.lang.Class.forName() with various inputs. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ClassForName { + + private String aName, bName, cName; + + @Setup + public void setup() { + aName = A.class.getName(); + bName = B.class.getName(); + cName = C.class.getName(); + } + + /** Calls Class.forName with the same name over and over again. The class asked for exists. */ + @Benchmark + public void test1(Blackhole bh) throws ClassNotFoundException { + bh.consume(Class.forName(aName)); + } + + /** Calls Class.forName with the three different names over and over again. All classes asked for exist. */ + @Benchmark + public void test3(Blackhole bh) throws ClassNotFoundException { + bh.consume(Class.forName(aName)); + bh.consume(Class.forName(bName)); + bh.consume(Class.forName(cName)); + } + + static class A {} + static class B {} + static class C {} +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/Clone.java b/test/micro/classes/org/openjdk/bench/java/lang/Clone.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/Clone.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.BitSet; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Clone { + + private BitSet testObj1; + private Date testObj2; + private char[] testObj3; + + @Setup + public void setup() { + testObj1 = new BitSet(10); + testObj2 = new Date(); + testObj3 = new char[5]; + } + + /** Calls clone on three different types. The types are java.util.BitSet, java.util.Date and char[]. */ + @Benchmark + public void cloneThreeDifferent(Blackhole bh) { + bh.consume(testObj1.clone()); + bh.consume(testObj2.clone()); + bh.consume(testObj3.clone()); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/java/lang/FloatingDecimal.java b/test/micro/classes/org/openjdk/bench/java/lang/FloatingDecimal.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/FloatingDecimal.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Tests for sun.misc.FloatingDecimal. Performs floating point number to String conversions. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class FloatingDecimal { + + private double[] randomArray, twoDecimalsArray, integerArray; + private static final int TESTSIZE = 1000; + + @Setup + public void setup() { + Random r = new Random(1123); + randomArray = new double[TESTSIZE]; + twoDecimalsArray = new double[TESTSIZE]; + integerArray = new double[TESTSIZE]; + for (int i = 0; i < TESTSIZE; i++) { + randomArray[i] = r.nextDouble() * 10000.0D; + twoDecimalsArray[i] = ((double) (10000 - r.nextInt(20000))) / 100; + integerArray[i] = (double) (100 - r.nextInt(200)); + } + } + + /** Tests Double.toString on double values generated from Random.nextDouble() */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void randomDoubleToString(Blackhole bh) { + for (double d : randomArray) { + bh.consume(Double.toString(d)); + } + } + + /** Tests Double.toString on double values that are integers between -100 and 100. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void integerDoubleToString(Blackhole bh) { + for (double d : integerArray) { + bh.consume(Double.toString(d)); + } + } + + /** Tests Double.toString on double values that are between -100 and 100 and have two decimal digits. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void twoDecimalsDoubleToString(Blackhole bh) { + for (double d : twoDecimalsArray) { + bh.consume(Double.toString(d)); + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/GetStackTrace.java b/test/micro/classes/org/openjdk/bench/java/lang/GetStackTrace.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/GetStackTrace.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +/** + * Tests Thread.getStackTrace() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class GetStackTrace { + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public StackTraceElement[] depth0() { + return Thread.currentThread().getStackTrace(); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public StackTraceElement[] depth1() { + return depth0(); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public StackTraceElement[] depth2() { + return depth1(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/Integers.java b/test/micro/classes/org/openjdk/bench/java/lang/Integers.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/Integers.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Tests java.lang.Integer + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class Integers { + + @Param("500") + private int size; + + private String[] strings; + + @Setup + public void setup() { + Random r = new Random(0); + strings = new String[size]; + for (int i = 0; i < size; i++) { + strings[i] = "" + (r.nextInt(10000) - 5000); + } + } + + @Benchmark + public void parseInt(Blackhole bh) { + for (String s : strings) { + bh.consume(Integer.parseInt(s)); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/Longs.java b/test/micro/classes/org/openjdk/bench/java/lang/Longs.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/Longs.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class Longs { + + @Param("500") + private int size; + + private long[] longArraySmall; + private long[] longArrayBig; + + @Setup + public void setup() { + longArraySmall = new long[size]; + longArrayBig = new long[size]; + for (int i = 0; i < size; i++) { + longArraySmall[i] = 100L * i + i + 103L; + longArrayBig[i] = ((100L * i + i) << 32) + 4543 + i * 4; + } + } + + /** Performs toString on a bunch of java.lang.Long:s, all with small values, just a couple of digits. */ + @Benchmark + @Threads(Threads.MAX) + public void toStringSmall(Blackhole bh) { + for (long value : longArraySmall) { + bh.consume(Long.toString(value)); + } + } + + /** Performs toString on a bunch of java.lang.Long:s, all with large values, around 10 digits. */ + @Benchmark + @Threads(Threads.MAX) + public void toStringBig(Blackhole bh) { + for (long value : longArrayBig) { + bh.consume(Long.toString(value)); + } + } + + /* + * Have them public to avoid total unrolling + */ + public int innerLoops = 1500; + + @Benchmark + @Threads(Threads.MAX) + public long repetitiveSubtraction() { + long x = 127, dx = 0; + + for (int i = 0; i < innerLoops; i++) { + x -= dx; + dx = (dx - x); + } + return x; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/NewInstance.java b/test/micro/classes/org/openjdk/bench/java/lang/NewInstance.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/NewInstance.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring java.lang.Class.newInstance speed. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class NewInstance { + + public Class[] samePublicClasses; + public Class[] differentPublicClasses; + public Class[] differentPublicClassesConstant; + public Class[] sameProtectedClasses; + public Class[] differentProtectedClasses; + + @Setup + public void setup() { + samePublicClasses = new Class[]{Apub.class, Apub.class, Apub.class}; + differentPublicClasses = new Class[]{Apub.class, Bpub.class, Cpub.class}; + differentPublicClassesConstant = new Class[]{Apub.class, Bpub.class, Cpub.class}; + sameProtectedClasses = new Class[]{Apro.class, Apro.class, Apro.class}; + differentProtectedClasses = new Class[]{Apro.class, Bpro.class, Cpro.class}; + } + + /** + * Performs Class.newInstance on the same class over and over again. That it is the same class is not provable at + * compile time. The class is protected. + */ + @Benchmark + public void threeSameProtected(Blackhole bh) throws IllegalAccessException, InstantiationException { + for (Class cl : sameProtectedClasses) { + bh.consume(cl.newInstance()); + } + } + + /** + * Performs Class.newInstance on three different classes, just allocating one instance of one class at a time. The + * classes are all protected. + */ + @Benchmark + public void threeDifferentProtected(Blackhole bh) throws IllegalAccessException, InstantiationException { + for (Class cl : differentProtectedClasses) { + bh.consume(cl.newInstance()); + } + } + + /** + * Performs Class.newInstance on the same class over and over again. That it is the same class is not provable at + * compile time. The class is public. + */ + @Benchmark + public void threeSamePublic(Blackhole bh) throws IllegalAccessException, InstantiationException { + for (Class cl : samePublicClasses) { + bh.consume(cl.newInstance()); + } + } + + /** + * Performs Class.newInstance on three different classes, just allocating one instance of one class at a time. The + * classes are all public. + */ + @Benchmark + public void threeDifferentPublic(Blackhole bh) throws IllegalAccessException, InstantiationException { + for (Class cl : differentPublicClasses) { + bh.consume(cl.newInstance()); + } + } + + /** + * Performs Class.newInstance on three different classes, just allocating one instance of one class at a time. The + * classes are all public. + */ + @Benchmark + public void threeDifferentPublicConstant(Blackhole bh) throws IllegalAccessException, InstantiationException { + bh.consume(Apub.class.newInstance()); + bh.consume(Bpub.class.newInstance()); + bh.consume(Cpub.class.newInstance()); + } + + @Benchmark + public void threeDifferentPublicFinal(Blackhole bh) throws IllegalAccessException, InstantiationException { + for (Class cl : differentPublicClassesConstant) { + bh.consume(cl.newInstance()); + } + } + + /* Protected test classes */ + static class Apro {} + static class Bpro {} + static class Cpro {} + + /* Public test classes */ + public static class Apub {} + public static class Bpub {} + public static class Cpub {} + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ObjectHashCode.java b/test/micro/classes/org/openjdk/bench/java/lang/ObjectHashCode.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ObjectHashCode.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +/** + * This benchmark assesses different hashCode strategies in HotSpot + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ObjectHashCode { + + @Benchmark + @Fork + public int mode_default() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=0"}) + public int mode_0() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=1"}) + public int mode_1() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=2"}) + public int mode_2() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=3"}) + public int mode_3() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=4"}) + public int mode_4() { + return System.identityHashCode(new Object()); + } + + @Benchmark + @Fork(jvmArgsPrepend = {"-XX:+UnlockExperimentalVMOptions", "-XX:hashCode=5"}) + public int mode_5() { + return System.identityHashCode(new Object()); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringBuffers.java b/test/micro/classes/org/openjdk/bench/java/lang/StringBuffers.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringBuffers.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringBuffers { + + private String name; + private String blaha; + private Sigurd sig; + + @Setup + public void setup() { + name = "joe"; + blaha = "sniglogigloienlitenapasomarengrodasjukadjavelhej"; + sig = new Sigurd(); + } + + @Benchmark + public String appendAndToString() { + return "MyStringBuffer named:" + ((name == null) ? "unknown" : name) + "."; + } + + @Benchmark + public String toStringComplex() { + return sig.toString(); + } + + static class Sigurd { + int x; + byte y; + String z = "yahoo"; + + @Override + public String toString() { + return Integer.toString(x) + "_" + Integer.toString((int) y) + "_" + z + "_"; + } + } + + @Benchmark + public String substring() { + return blaha.substring(30, 35); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringBuilders.java b/test/micro/classes/org/openjdk/bench/java/lang/StringBuilders.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringBuilders.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringBuilders { + + private String[] strings; + private String[] str3p4p2; + private String[] str16p8p7; + private String[] str3p9p8; + private String[] str22p40p31; + + @Setup + public void setup() { + strings = new String[]{"As", "your", "attorney,", "I", + "advise", "you", "to", "drive", "at", "top", "speed", "it'll", + "be", "a", "god", "damn", "miracle", "if", "we", "can", "get", + "there", "before", "you", "turn", "into", "a", "wild", "animal."}; + str3p4p2 = new String[]{"123", "1234", "12"}; + str16p8p7 = new String[]{"1234567890123456", "12345678", "1234567"}; + str3p9p8 = new String[]{"123", "123456789", "12345678"}; + str22p40p31 = new String[]{"1234567890123456789012", "1234567890123456789012345678901234567890", "1234567890123456789012345678901"}; + } + + /** StringBuilder wins over StringMaker. */ + @Benchmark + public String concat3p4p2() throws Exception { + return new StringBuilder(String.valueOf(str3p4p2[0])).append(str3p4p2[1]).append(str3p4p2[2]).toString(); + } + + /** StringBuilder wins over StringMaker. */ + @Benchmark + public String concat16p8p7() throws Exception { + return new StringBuilder(String.valueOf(str16p8p7[0])).append(str16p8p7[1]).append(str16p8p7[2]).toString(); + } + + /** StringMaker wins over StringBuilder since the two last strings causes StringBuilder to do expand. */ + @Benchmark + public String concat3p9p8() throws Exception { + return new StringBuilder(String.valueOf(str3p9p8[0])).append(str3p9p8[1]).append(str3p9p8[2]).toString(); + } + + /** StringMaker wins over StringBuilder. */ + @Benchmark + public String concat22p40p31() throws Exception { + return new StringBuilder(String.valueOf(str22p40p31[0])).append(str22p40p31[1]).append(str22p40p31[2]).toString(); + } + + @Benchmark + public StringBuilder appendLoop8() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 8; i++) { + sb.append(strings[i]); + } + return sb; + } + + @Benchmark + public StringBuilder appendLoop16() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 16; i++) { + sb.append(strings[i]); + } + return sb; + } + + @Benchmark + public String toStringCharWithChar1() { + StringBuilder result = new StringBuilder(); + result.append('a'); + return result.toString(); + } + + @Benchmark + public String toStringCharWithChar2() { + StringBuilder result = new StringBuilder(); + result.append('a'); + result.append('p'); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithChar4() { + StringBuilder result = new StringBuilder(); + result.append('a'); + result.append('p'); + result.append('a'); + result.append(' '); + return result.toString(); + } + + @Benchmark + public String toStringCharWithChar8() { + StringBuilder result = new StringBuilder(); + result.append('a'); + result.append('p'); + result.append('a'); + result.append(' '); + result.append('a'); + result.append('p'); + result.append('a'); + result.append(' '); + return result.toString(); + } + + @Benchmark + public String toStringCharWithChar16() { + StringBuilder result = new StringBuilder(); + result.append('a'); + result.append('b'); + result.append('c'); + result.append('d'); + result.append('e'); + result.append('f'); + result.append('g'); + result.append('h'); + result.append('i'); + result.append('j'); + result.append('k'); + result.append('l'); + result.append('m'); + result.append('n'); + result.append('o'); + result.append('p'); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithString8() { + StringBuilder result = new StringBuilder(); + result.append("a"); + result.append("b"); + result.append("c"); + result.append("d"); + result.append("e"); + result.append("f"); + result.append("g"); + result.append("h"); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithString16() { + StringBuilder result = new StringBuilder(); + result.append("a"); + result.append("b"); + result.append("c"); + result.append("d"); + result.append("e"); + result.append("f"); + result.append("g"); + result.append("h"); + result.append("i"); + result.append("j"); + result.append("k"); + result.append("l"); + result.append("m"); + result.append("n"); + result.append("o"); + result.append("p"); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithInt8() { + StringBuilder result = new StringBuilder(); + result.append(2048); + result.append(31337); + result.append(0xbeefcace); + result.append(9000); + result.append(4711); + result.append(1337); + result.append(2100); + result.append(2600); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithBool8() { + StringBuilder result = new StringBuilder(); + result.append(true); + result.append(false); + result.append(true); + result.append(true); + result.append(false); + result.append(true); + result.append(false); + result.append(false); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithFloat8() { + StringBuilder result = new StringBuilder(); + result.append(113.110F); + result.append(156456.36435637F); + result.append(65436434.64632F); + result.append(42654634.64540F); + result.append(63464351.64537F); + result.append(634564.645711F); + result.append(64547.64311F); + result.append(4763456341.64531F); + return result.toString(); + } + + + @Benchmark + public String toStringCharWithMixed8() { + StringBuilder result = new StringBuilder(); + result.append('a'); + result.append("stringelinglinglinglong"); + result.append('a'); + result.append("stringelinglinglinglong"); + result.append('a'); + result.append("stringelinglinglinglong"); + result.append('p'); + result.append("stringelinglinglinglong"); + return result.toString(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringConcat.java b/test/micro/classes/org/openjdk/bench/java/lang/StringConcat.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringConcat.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Trivial String concatenation benchmark. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringConcat { + + public int intValue = 4711; + + public String stringValue = String.valueOf(intValue); + + public Object objectValue = Long.valueOf(intValue); + + public boolean boolValue = true; + + public byte byteValue = (byte)-128; + + @Benchmark + public String concatConstInt() { + return "string" + intValue; + } + + @Benchmark + public String concatConstString() { + return "string" + stringValue; + } + + @Benchmark + public String concatConstIntConstInt() { + return "string" + intValue + "string" + intValue; + } + + @Benchmark + public String concatConstStringConstInt() { + return "string" + stringValue + "string" + intValue; + } + + @Benchmark + public String concatConst4String() { + return "string" + stringValue + stringValue + stringValue + stringValue; + } + + @Benchmark + public String concatConst2String() { + return "string" + stringValue + stringValue; + } + + @Benchmark + public String concatConstBoolByte() { + return "string" + boolValue + byteValue; + } + + @Benchmark + public String concatConst6String() { + return "string" + stringValue + stringValue + stringValue + stringValue + stringValue + stringValue; + } + + @Benchmark + public String concatConst6Object() { + return "string" + objectValue + objectValue + objectValue + objectValue + objectValue + objectValue; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringHashCode.java b/test/micro/classes/org/openjdk/bench/java/lang/StringHashCode.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringHashCode.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Performance test of String.hashCode() function + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringHashCode { + + private String hashcode; + private String hashcode0; + + @Setup + public void setup() { + hashcode = "abcdefghijkl"; + hashcode0 = new String(new char[]{72, 90, 100, 89, 105, 2, 72, 90, 100, 89, 105, 2}); + } + + /** + * Benchmark testing String.hashCode() with a regular 12 char string with + * the result possibly cached in String + */ + @Benchmark + public int cached() { + return hashcode.hashCode(); + } + + /** + * Benchmark testing String.hashCode() with a 12 char string with the + * hashcode = 0 forcing the value to always be recalculated. + */ + @Benchmark + public int notCached() { + return hashcode0.hashCode(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringHttp.java b/test/micro/classes/org/openjdk/bench/java/lang/StringHttp.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringHttp.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringHttp { + + private byte[] httpRequest; + private String[] httpResponse; + private byte[] buf; + + @Setup + public void setup() { + buf = new byte[4080]; + httpRequest = "GET /foo/bar/baz HTTP/1.1\nHost: foo.com\n".getBytes(); + httpResponse = new String[]{"Date: 4/20/2003 10:21:31", "Last-Modified: 4/15/2003 10:21:31", + "Content-Length: 1234", "", "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz", + "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz", + "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz", + "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz", + "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz"}; + } + + @Benchmark + public void parseRequest(Blackhole bh) { + bh.consume(new String(httpRequest, 0, 3)); + bh.consume(new String(httpRequest, 5, 11)); + bh.consume(new String(httpRequest, 17, 8)); + bh.consume(new String(httpRequest, 32, 7)); + } + + @Benchmark + public int bufferResponse() { + int pos = 0; + int n = httpResponse.length; + + for (String s : httpResponse) { + byte[] b = s.getBytes(); + int len = b.length; + + System.arraycopy(b, 0, buf, pos, len); + pos += len; + buf[pos++] = '\n'; + } + return n; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringIndexOf.java b/test/micro/classes/org/openjdk/bench/java/lang/StringIndexOf.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringIndexOf.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringIndexOf { + + private String dataString; + private String searchString; + private String dataStringBig; + private String searchStringBig; + private String data; + private String sub; + private String shortSub1; + private String data2; + private String shortSub2; + + @Setup + public void setup() { + dataString = "ngdfilsoscargfdgf"; + searchString = "oscar"; + dataStringBig = "2937489745890797905764956790452976742965790437698498409583479067ngdcapaapapapasdkajdlkajskldjaslkjdlkasjdsalkjas"; + searchStringBig = "capaapapapasdkajdlkajskldjaslkjdlkasjdsalk"; + data = "0000100101010010110101010010101110101001110110101010010101010010000010111010101010101010100010010101110111010101101010100010010100001010111111100001010101001010100001010101001010101010111010010101010101010101010101010"; + sub = "10101010"; + shortSub1 = "1"; + data2 = "00001001010100a10110101010010101110101001110110101010010101010010000010111010101010101010a100010010101110111010101101010100010010a100a0010101111111000010101010010101000010101010010101010101110a10010101010101010101010101010"; + shortSub2 = "a"; + } + + /** IndexOf Micros Strings */ + + /** + * Benchmarks String.indexOf with a rather small String to search and a rather small String to search for. The + * searched string contains the string that is searched for. + */ + @Benchmark + public int success() { + return dataString.indexOf(searchString, 2); + } + + /** + * Benchmarks String.indexOf with a rather big String to search and a rather big String to search for. The searched + * string contains the string that is searched for. + */ + @Benchmark + public int successBig() { + return dataStringBig.indexOf(searchStringBig, 2); + } + + /** + * Benchmarks String.indexOf with a rather big String. Search repeatedly for a matched that is 8 chars and most + * oftenly will require a inner lopp match in String.indexOf with sse42. + */ + @Benchmark + public int advancedWithMediumSub() { + int index = 0; + int dummy = 0; + while ((index = data.indexOf(sub, index)) > -1) { + index++; + dummy += index; + } + return dummy; + } + + + /** + * Benchmarks String.indexOf with a rather big String. Search repeatedly for a matched that is 1 chars will find a + * huge amount of matches + */ + @Benchmark + public int advancedWithShortSub1() { + int dummy = 0; + int index = 0; + while ((index = data.indexOf(shortSub1, index)) > -1) { + index++; + dummy += index; + } + return dummy; + } + + + /** + * Benchmarks String.indexOf with a rather big String. Search repeatedly for a matched that is 1 chars but only with + * a few matches. + */ + @Benchmark + public int advancedWithShortSub2() { + int dummy = 0; + int index = 0; + while ((index = data2.indexOf(shortSub2, index)) > -1) { + index++; + dummy += index; + } + return dummy; + } + + @Benchmark + public void constantPattern() { + String tmp = "simple-hash:SHA-1/UTF-8"; + if (!tmp.contains("SHA-1")) { + throw new RuntimeException("indexOf failed"); + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringOther.java b/test/micro/classes/org/openjdk/bench/java/lang/StringOther.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringOther.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringOther { + + private String testString; + private Random rnd; + + private String str1, str2, str3, str4; + + @Setup + public void setup() { + testString = "Idealism is what precedes experience; cynicism is what follows."; + str1 = "vm-guld vm-guld vm-guld"; + str2 = "vm-guld vm-guld vm-guldx"; + str3 = "vm-guld vm-guld vm-guldx"; + str4 = "adadaskasdjierudks"; + rnd = new Random(); + } + + @Benchmark + public void charAt(Blackhole bh) { + for (int i = 0; i < testString.length(); i++) { + bh.consume(testString.charAt(i)); + } + } + + @Benchmark + public int compareTo() { + int total = 0; + total += str1.compareTo(str2); + total += str2.compareTo(str3); + total += str3.compareTo(str4); + return total; + } + + /** + * Creates (hopefully) unique Strings and internizes them, creating a zillion forgettable strings in the JVMs string + * pool. + *

+ * This will test 1.) The data structure/whatever for getting and adding Strings to intern table. 2.) The + * intern-caches (java) behaviour on negative lookup (the string is new) 3.) GC's handling of weak handles. Since + * every gc we must process and pretty much kill a zillion interned strings that are now not referenced anymore, the + * majority of GC time will be spent in handle processing. So we get a picture of how well the pathological case of + * this goes. + */ + @Benchmark + public String internUnique() { + return String.valueOf(rnd.nextInt()).intern(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/StringUpperLower.java b/test/micro/classes/org/openjdk/bench/java/lang/StringUpperLower.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/StringUpperLower.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StringUpperLower { + + private String strLowerCase; + private String strMixedCase; + private String strUpperCase; + + @Setup + public void setup() { + strLowerCase = "this is a simple string with different cases"; + strMixedCase = "This IS a SImpLE strING wITh DiFfErEnT CASeS"; + strUpperCase = "THIS IS A SIMPLE STRING WITH DIFFERENT CASES"; + } + + @Benchmark + public String lowerToLower() { + return strLowerCase.toLowerCase(); + } + + @Benchmark + public String mixedToLower() { + return strMixedCase.toLowerCase(); + } + + @Benchmark + public String upperToLower() { + return strUpperCase.toLowerCase(); + } + + @Benchmark + public String lowerToUpper() { + return strLowerCase.toUpperCase(); + } + + @Benchmark + public String mixedToUpper() { + return strMixedCase.toUpperCase(); + } + + @Benchmark + public String upperToUpper() { + return strUpperCase.toUpperCase(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/Systems.java b/test/micro/classes/org/openjdk/bench/java/lang/Systems.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/Systems.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class Systems { + + @Benchmark + public long currentTimeMillis() { + return System.currentTimeMillis(); + } + + @Benchmark + public long nanoTime() { + return System.nanoTime(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/ThreadStartJoin.java b/test/micro/classes/org/openjdk/bench/java/lang/ThreadStartJoin.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/ThreadStartJoin.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.TimeUnit; + +/** + * Test to launch and gather threads. Measure time for different parts. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +public class ThreadStartJoin { + + private static final int THREADS = Runtime.getRuntime().availableProcessors(); + + private Thread[] ts; + + @Benchmark + public void test() throws InterruptedException { + ts = new TestThread[THREADS]; + + for (int i = 0; i < THREADS; i++) { + ts[i] = new TestThread(); + } + + for (int i = 0; i < THREADS; i++) { + ts[i].start(); + } + + for (Thread mythread : ts) { + mythread.join(); + + if (mythread.isAlive()) { + throw new IllegalStateException("Couldn't join in time in LPHhello."); + } + } + } + + @TearDown + public final void cleanup() { + if (ts != null) { + for (Thread t : ts) { + if (t != null) { + t.interrupt(); + } + } + ts = null; + } + } + + static final class TestThread extends Thread { + private static int num = 0; + + public TestThread() { + super(TestThread.name()); + } + + private synchronized static String name() { + return "TestThread-" + num++; + } + + public void run() { + // do nothing + } + + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.lang.invoke.VolatileCallSite; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * This benchmark evaluates INDY performance under dynamic target updates. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class CallSiteSetTarget { + + /* + * Implementation notes: + * - This test makes sense for mutable and volatile call sites only + * - Multiple threads are calling the same callsite, and invalidator thread tries to swap target on the fly. + * - Additional baseline includes "raw" test, calling callsite's MH directly + */ + + private static volatile CallSite cs; + + private static MethodHandle doCall1; + private static MethodHandle doCall2; + + static { + try { + doCall1 = MethodHandles.lookup().findVirtual(CallSiteSetTarget.class, "call1", MethodType.methodType(int.class)); + doCall2 = MethodHandles.lookup().findVirtual(CallSiteSetTarget.class, "call2", MethodType.methodType(int.class)); + cs = new MutableCallSite(doCall1); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + private int i1; + private int i2; + + public int call1() { + return i1++; + } + + public int call2() { + return i2++; + } + + @Benchmark + public int baselineRaw() throws Throwable { + return (int) cs.getTarget().invokeExact(this); + } + + @Benchmark + public int testMutable() throws Throwable { + return (int) INDY_Mutable().invokeExact(this); + } + + @Benchmark + public int testVolatile() throws Throwable { + return (int) INDY_Volatile().invokeExact(this); + } + + /* =========================== INDY TRAMPOLINES ============================== */ + + private static MethodType MT_bsm() { + shouldNotCallThis(); + return MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); + } + + private static MethodHandle MH_bsm_Mutable() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Mutable", MT_bsm()); + } + + private static MethodHandle MH_bsm_Volatile() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Volatile", MT_bsm()); + } + + private static MethodHandle INDY_Mutable() throws Throwable { + shouldNotCallThis(); + return ((CallSite) MH_bsm_Mutable().invoke(MethodHandles.lookup(), "doCall1", MethodType.methodType(int.class, CallSiteSetTarget.class))).dynamicInvoker(); + } + + private static MethodHandle INDY_Volatile() throws Throwable { + shouldNotCallThis(); + return ((CallSite) MH_bsm_Volatile().invoke(MethodHandles.lookup(), "doCall1", MethodType.methodType(int.class, CallSiteSetTarget.class))).dynamicInvoker(); + } + + public static CallSite bsm_Mutable(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteSetTarget.class) { + if (cs == null) + cs = new MutableCallSite(doCall1); + return cs; + } + } + + public static CallSite bsm_Volatile(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteSetTarget.class) { + if (cs == null) + cs = new VolatileCallSite(doCall1); + return cs; + } + } + + private static void shouldNotCallThis() { + // if this gets called, the transformation has not taken place + throw new AssertionError("this code should be statically transformed away by Indify"); + } + + /* =========================== INVALIDATE LOGIC ============================== */ + + private final static Invalidator invalidator = new Invalidator(); + + @Setup + public void setup() { + invalidator.start(); + } + + @TearDown + public void tearDown() throws InterruptedException { + invalidator.stop(); + } + + public static class Invalidator implements Runnable { + + private final long period = Integer.getInteger("period", 1000); + + private final AtomicBoolean started = new AtomicBoolean(); + private volatile Thread thread; + + @Override + public void run() { + try { + while(!Thread.interrupted()) { + if (cs != null) { + cs.setTarget(doCall1); + } + TimeUnit.MICROSECONDS.sleep(period); + + if (cs != null) { + cs.setTarget(doCall2); + } + TimeUnit.MICROSECONDS.sleep(period); + } + } catch (InterruptedException e) { + // do nothing + } + } + + public void start() { + if (started.compareAndSet(false, true)) { + thread = new Thread(this); + thread.setPriority(Thread.MAX_PRIORITY); + thread.start(); + } + } + + public void stop() { + if (thread != null) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + started.set(false); + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.lang.invoke.VolatileCallSite; +import java.util.concurrent.TimeUnit; + +/** + * This benchmark evaluates INDY performance under dynamic target updates. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class CallSiteSetTargetSelf { + + /* + * Implementation notes: + * - This test makes sense for mutable and volatile call sites only + * - Multiple threads are calling the same callsite, and each call is swapping the target. + * - Additional baseline includes "raw" test, calling callsite's MH directly + * + * - NOTE: invalidating shared target callsite is very bad with multiple threads. + * I.e. this test is inherently non-scalable. + */ + + private static CallSite cs; + + private static MethodHandle doCall1; + private static MethodHandle doCall2; + + static { + try { + doCall1 = MethodHandles.lookup().findVirtual(CallSiteSetTargetSelf.class, "call1", MethodType.methodType(int.class)); + doCall2 = MethodHandles.lookup().findVirtual(CallSiteSetTargetSelf.class, "call2", MethodType.methodType(int.class)); + cs = new MutableCallSite(doCall1); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + private int i1; + private int i2; + + public int call1() { + cs.setTarget(doCall2); + return i1++; + } + + public int call2() { + cs.setTarget(doCall1); + return i2++; + } + + @Benchmark + public int baselineRaw() throws Throwable { + return (int) cs.getTarget().invokeExact(this); + } + + @Benchmark + public int testMutable() throws Throwable { + return (int) INDY_Mutable().invokeExact(this); + } + + @Benchmark + public int testVolatile() throws Throwable { + return (int) INDY_Volatile().invokeExact(this); + } + + /* =========================== INDY TRAMPOLINES ============================== */ + + private static MethodType MT_bsm() { + shouldNotCallThis(); + return MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); + } + + private static MethodHandle MH_bsm_Mutable() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Mutable", MT_bsm()); + } + + private static MethodHandle MH_bsm_Volatile() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Volatile", MT_bsm()); + } + + private static MethodHandle INDY_Mutable() throws Throwable { + shouldNotCallThis(); + return ((CallSite) MH_bsm_Mutable().invoke(MethodHandles.lookup(), "doCall1", MethodType.methodType(int.class, CallSiteSetTargetSelf.class))).dynamicInvoker(); + } + + private static MethodHandle INDY_Volatile() throws Throwable { + shouldNotCallThis(); + return ((CallSite) MH_bsm_Volatile().invoke(MethodHandles.lookup(), "doCall1", MethodType.methodType(int.class, CallSiteSetTargetSelf.class))).dynamicInvoker(); + } + + public static CallSite bsm_Mutable(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteSetTarget.class) { + if (cs == null) + cs = new MutableCallSite(doCall1); + return cs; + } + } + + public static CallSite bsm_Volatile(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteSetTarget.class) { + if (cs == null) + cs = new VolatileCallSite(doCall1); + return cs; + } + } + + private static void shouldNotCallThis() { + // if this gets called, the transformation has not taken place + throw new AssertionError("this code should be statically transformed away by Indify"); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteStable.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteStable.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/CallSiteStable.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.lang.invoke.VolatileCallSite; +import java.util.concurrent.TimeUnit; + +/** + * This benchmark evaluates INDY performance when call sites are not changed. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class CallSiteStable { + + /* + * Implementation notes: + * - Test is calling simple method via INDY + * - Additional baseline includes "raw" test, calling target method directly in virtual and static modes + */ + + private static java.lang.invoke.CallSite cs; + + private static MethodHandle doCallMH; + + static { + try { + doCallMH = MethodHandles.lookup().findVirtual(CallSiteStable.class, "doCall", MethodType.methodType(int.class, int.class)); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + private int i; + + public int doCall(int value) { + return value + 1; + } + + public static int doCallStatic(int value) { + return value + 1; + } + + @Benchmark + public void baselineVirtual() { + i = doCall(i); + } + + @Benchmark + public void baselineStatic() { + i = doCallStatic(i); + } + + @Benchmark + public void testConstant() throws Throwable { + i = (int) INDY_Constant().invokeExact(this, i); + } + + @Benchmark + public void testMutable() throws Throwable { + i = (int) INDY_Mutable().invokeExact(this, i); + } + + @Benchmark + public void testVolatile() throws Throwable { + i = (int) INDY_Volatile().invokeExact(this, i); + } + + /* =========================== INDY TRAMPOLINES ============================== */ + + private static MethodType MT_bsm() { + shouldNotCallThis(); + return MethodType.methodType(java.lang.invoke.CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); + } + + private static MethodHandle MH_bsm_Constant() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Constant", MT_bsm()); + } + + private static MethodHandle MH_bsm_Mutable() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Mutable", MT_bsm()); + } + + private static MethodHandle MH_bsm_Volatile() throws ReflectiveOperationException { + shouldNotCallThis(); + return MethodHandles.lookup().findStatic(MethodHandles.lookup().lookupClass(), "bsm_Volatile", MT_bsm()); + } + + private static MethodHandle INDY_Constant() throws Throwable { + shouldNotCallThis(); + return ((java.lang.invoke.CallSite) MH_bsm_Constant().invoke(MethodHandles.lookup(), "doCall", MethodType.methodType(int.class, CallSiteStable.class, int.class))).dynamicInvoker(); + } + private static MethodHandle INDY_Mutable() throws Throwable { + shouldNotCallThis(); + return ((java.lang.invoke.CallSite) MH_bsm_Mutable().invoke(MethodHandles.lookup(), "doCall", MethodType.methodType(int.class, CallSiteStable.class, int.class))).dynamicInvoker(); + } + private static MethodHandle INDY_Volatile() throws Throwable { + shouldNotCallThis(); + return ((java.lang.invoke.CallSite) MH_bsm_Volatile().invoke(MethodHandles.lookup(), "doCall", MethodType.methodType(int.class, CallSiteStable.class, int.class))).dynamicInvoker(); + } + + public static java.lang.invoke.CallSite bsm_Constant(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteStable.class) { + if (cs == null) + cs = new ConstantCallSite(doCallMH); + return cs; + } + } + + public static java.lang.invoke.CallSite bsm_Mutable(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteStable.class) { + if (cs == null) + cs = new MutableCallSite(doCallMH); + return cs; + } + } + + public static java.lang.invoke.CallSite bsm_Volatile(MethodHandles.Lookup lookup, String name, MethodType type) { + synchronized (CallSiteStable.class) { + if (cs == null) + cs = new VolatileCallSite(doCallMH); + return cs; + } + } + + private static void shouldNotCallThis() { + // if this gets called, the transformation has not taken place + throw new AssertionError("this code should be statically transformed away by Indify"); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupAcquire.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupAcquire.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupAcquire.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.lookup/publicLookup() acquiring performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class LookupAcquire { + + /* + Implementation notes: + - this test assesses acquiring lookup object only + - baseline includes returning cached lookup object, i.e. measures infra overheads + - additional baseline includes allocating object to understand Lookup instantiation costs + - cached instance is static, because that provides (unbeatably) best performance + */ + + public static MethodHandles.Lookup cached; + + @Setup + public void setup() { + cached = MethodHandles.lookup(); + } + + @Benchmark + public MethodHandles.Lookup baselineCached() throws Exception { + return cached; + } + + @Benchmark + public MyLookup baselineNew() throws Exception { + return new MyLookup(Object.class, 1); + } + + @Benchmark + public MethodHandles.Lookup testPublicLookup() throws Exception { + return MethodHandles.publicLookup(); + } + + @Benchmark + public MethodHandles.Lookup testLookup() throws Exception { + return MethodHandles.lookup(); + } + + /** + * Dummy Lookup-looking class. + * Lookup is final, and all constructors are private. + * This class mocks the hotpath. + */ + private static class MyLookup { + private final Class klass; + private final int mode; + + public MyLookup(Class klass, int i) { + this.klass = klass; + this.mode = i; + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandle.lookup() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class LookupDefaultFind { + + /* + Implementation notes: + - does not test findSpecial, since the privileges of this Bench is not enough to access private members + */ + + @Benchmark + public MethodHandle testConstructor() throws Exception { + return MethodHandles.lookup().findConstructor(Victim.class, MethodType.methodType(void.class)); + } + + @Benchmark + public MethodHandle testGetter() throws Exception { + return MethodHandles.lookup().findGetter(Victim.class, "field", int.class); + } + + @Benchmark + public MethodHandle testSetter() throws Exception { + return MethodHandles.lookup().findSetter(Victim.class, "field", int.class); + } + + @Benchmark + public MethodHandle testStatic() throws Exception { + return MethodHandles.lookup().findStatic(Victim.class, "staticWork", MethodType.methodType(int.class)); + } + + @Benchmark + public MethodHandle testStaticGetter() throws Exception { + return MethodHandles.lookup().findStaticGetter(Victim.class, "staticField", int.class); + } + + @Benchmark + public MethodHandle testStaticSetter() throws Exception { + return MethodHandles.lookup().findStaticSetter(Victim.class, "staticField", int.class); + } + + @Benchmark + public MethodHandle testVirtual() throws Exception { + return MethodHandles.lookup().findVirtual(Victim.class, "virtualWork", MethodType.methodType(int.class)); + } + + public static class Victim { + + public static int staticField; + public int field; + + public Victim() { + // do nothing + } + + public int virtualWork() { + return 1; + } + + public static int staticWork() { + return 1; + } + + private int specialWork() { + return 1; + } + + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandle.publicLookup() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class LookupPublicFind { + + /* + Implementation notes: + - findSpecial is not tested, unable to do this with public lookup object + */ + + @Benchmark + public MethodHandle testConstructor() throws Exception { + return MethodHandles.publicLookup().findConstructor(Victim.class, MethodType.methodType(void.class)); + } + + @Benchmark + public MethodHandle testGetter() throws Exception { + return MethodHandles.publicLookup().findGetter(Victim.class, "field", int.class); + } + + @Benchmark + public MethodHandle testSetter() throws Exception { + return MethodHandles.publicLookup().findSetter(Victim.class, "field", int.class); + } + + @Benchmark + public MethodHandle testStatic() throws Exception { + return MethodHandles.publicLookup().findStatic(Victim.class, "staticWork", MethodType.methodType(int.class)); + } + + @Benchmark + public MethodHandle testStaticGetter() throws Exception { + return MethodHandles.publicLookup().findStaticGetter(Victim.class, "staticField", int.class); + } + + @Benchmark + public MethodHandle testStaticSetter() throws Exception { + return MethodHandles.publicLookup().findStaticSetter(Victim.class, "staticField", int.class); + } + + @Benchmark + public MethodHandle testVirtual() throws Exception { + return MethodHandles.publicLookup().findVirtual(Victim.class, "virtualWork", MethodType.methodType(int.class)); + } + + public static class Victim { + + public static int staticField; + public int field; + + public Victim() { + // do nothing + } + + public int virtualWork() { + return 1; + } + + public static int staticWork() { + return 1; + } + + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Microbenchmark assesses MethodHandle.asCollector() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleAsCollector { + + /* + * Implementation notes: + * - simple array-parameter method is being called + * - baselineRaw calls method directly with dynamically instantiating the array + * - baselineCached calls method directly with pre-cached array + * - additional testCreate() test harnesses the collector acquisition performance + * - testCollector() can be faster than both baselines: it can wrapping array at all + */ + + public int i; + private static MethodHandle mh; + private static MethodHandle collectorMH; + private static int[] cachedArgs; + + @Setup + public void setup() throws IllegalAccessException, NoSuchMethodException { + mh = MethodHandles.lookup().findVirtual(MethodHandleAsCollector.class, "doWork", MethodType.methodType(void.class, int[].class)); + collectorMH = mh.asCollector(int[].class, 5); + cachedArgs = new int[]{1, 2, 3, 4, 5}; + } + + @Benchmark + public void baselineMH() throws Throwable { + mh.invokeExact(this, new int[] { 1, 2, 3, 4, 5 }); + } + + @Benchmark + public void baselineMHCached() throws Throwable { + mh.invokeExact(this, cachedArgs); + } + + @Benchmark + public void baselineRaw() throws Throwable { + doWork(new int[] { 1, 2, 3, 4, 5}); + } + + @Benchmark + public void baselineRawCached() throws Throwable { + doWork(cachedArgs); + } + + @Benchmark + public MethodHandle testCreate() { + return mh.asCollector(int[].class, 5); + } + + @Benchmark + public void testCollector() throws Throwable { + collectorMH.invokeExact(this, 1, 2, 3, 4, 5); + } + + public void doWork(int[] args) { + for (int a : args) { + i += a; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Microbenchmark assesses MethodHandle.asSpreader() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleAsSpreader { + + /* + * Implementation notes: + * - simple array-parameter method is being called + * - baselineRaw calls method directly with dynamically instantiating the array + * - baselineCached calls method directly with pre-cached array + * - additional testCreate() test harnesses the collector acquisition performance + * - testCollector() can be faster than both baselines: it can wrapping array at all + */ + + public int i; + private static MethodHandle mh; + private static MethodHandle spreaderMH; + private static int[] cachedArgs; + + @Setup + public void setup() throws IllegalAccessException, NoSuchMethodException { + mh = MethodHandles.lookup().findVirtual(MethodHandleAsSpreader.class, "doWork", MethodType.methodType(void.class, int.class, int.class, int.class, int.class, int.class)); + spreaderMH = mh.asSpreader(int[].class, 5); + cachedArgs = new int[]{1, 2, 3, 4, 5}; + } + + @Benchmark + public void baselineMH() throws Throwable { + mh.invokeExact(this, 1, 2, 3, 4, 5); + } + + @Benchmark + public void baselineRaw() throws Throwable { + doWork(1, 2, 3, 4, 5); + } + + @Benchmark + public MethodHandle testCreate() { + return mh.asSpreader(int[].class, 5); + } + + @Benchmark + public void testSpreader() throws Throwable { + spreaderMH.invokeExact(this, new int[] { 1, 2, 3, 4, 5 }); + } + + @Benchmark + public void testSpreaderCached() throws Throwable { + spreaderMH.invokeExact(this, cachedArgs); + } + + public void doWork(int arg1, int arg2, int arg3, int arg4, int arg5) { + i += (arg1 + arg2 + arg3 + arg4 + arg5); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Microbenchmark assesses MethodHandle.asVarargCollector() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleAsVarargsCollector { + + /* + * Implementation notes: + * - simple array-parameter method is being called + * - baselineRaw calls method directly with dynamically instantiating the array + * - baselineCached calls method directly with pre-cached array + * - additional testCreate() test harnesses the collector acquisition performance + * - testCollector() can be faster than both baselines: it can wrapping array at all + */ + + public int i; + private static MethodHandle mh; + private static MethodHandle collectorMH; + private static int[] cachedArgs; + + @Setup + public void setup() throws IllegalAccessException, NoSuchMethodException { + mh = MethodHandles.lookup().findVirtual(MethodHandleAsVarargsCollector.class, "doWork", MethodType.methodType(void.class, int[].class)); + collectorMH = mh.asVarargsCollector(int[].class); + cachedArgs = new int[]{1, 2, 3, 4, 5}; + } + + @Benchmark + public void baselineMH() throws Throwable { + mh.invoke(this, new int[] { 1, 2, 3, 4, 5 }); + } + + @Benchmark + public void baselineMHCached() throws Throwable { + mh.invoke(this, cachedArgs); + } + + @Benchmark + public void baselineRaw() throws Throwable { + doWork(1, 2, 3, 4, 5); + } + + @Benchmark + public void baselineRawCached() throws Throwable { + doWork(cachedArgs); + } + + @Benchmark + public MethodHandle testCreate() { + return mh.asVarargsCollector(int[].class); + } + + @Benchmark + public void testCollector() throws Throwable { + collectorMH.invoke(this, 1, 2, 3, 4, 5); + } + + public void doWork(int... args) { + for (int a : args) { + i += a; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark to assess basic MethodHandle performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleBasicInvoke { + + /* + * Implementation notes: + * - this is a very basic test, does not do any parameter conversion (in fact, no parameters at all) + * - baselines include calling method directly, and doing the same via reflection + * - baselineRaw is known to be super-fast with good inlining + */ + + private int i; + private static MethodHandle mh; + private static Method ref; + private static MethodHandle mhUnreflect; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findVirtual(MethodHandleBasicInvoke.class, "doWork", MethodType.methodType(int.class)); + + ref = MethodHandleBasicInvoke.class.getMethod("doWork"); + ref.setAccessible(true); + + mhUnreflect = MethodHandles.lookup().unreflect(ref); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(); + } + + @Benchmark + public int baselineReflect() throws Throwable { + return (int) ref.invoke(this); + } + + @Benchmark + public int testMH_Plain_Invoke() throws Throwable { + return (int) mh.invoke(this); + } + + @Benchmark + public int testMH_Plain_Exact() throws Throwable { + return (int) mh.invokeExact(this); + } + + @Benchmark + public int testMH_Unreflect_Invoke() throws Throwable { + return (int) mhUnreflect.invoke(this); + } + + @Benchmark + public int testMH_Unreflect_Exact() throws Throwable { + return (int) mhUnreflect.invokeExact(this); + } + + public int doWork() { + return i++; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandle.bindTo() binding performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleBindToBinding { + + /* + Implementation notes: + - calls static method to avoid binding "this" + - tests binding costs with multiple depth (C1, C2, C3) + - baseline includes naive side effect store + - lowering the binding cost will minimise both the spread between C1/C2/C3 and difference towards baseline + - this test performance will never reach the baseline + */ + + private MethodHandle mhOrig; + + @Setup + public void setup() throws Throwable { + mhOrig = MethodHandles.lookup().findStatic(MethodHandleBindToBinding.class, "doWork", + MethodType.methodType(Integer.class, Integer.class, Integer.class, Integer.class)); + } + + @Benchmark + public Object baselineRaw() { + return mhOrig; + } + + @Benchmark + public Object testBind_C1() throws Throwable { + MethodHandle mhCurry1 = mhOrig.bindTo(1); + return mhCurry1; + } + + @Benchmark + public Object testBind_C2() throws Throwable { + MethodHandle mhCurry1 = mhOrig.bindTo(1); + MethodHandle mhCurry2 = mhCurry1.bindTo(2); + return mhCurry2; + } + + @Benchmark + public Object testBind_C3() throws Throwable { + MethodHandle mhCurry1 = mhOrig.bindTo(1); + MethodHandle mhCurry2 = mhCurry1.bindTo(2); + MethodHandle mhCurry3 = mhCurry2.bindTo(3); + return mhCurry3; + } + + public static Integer doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses currying with MethodHandle.bindTo() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleBindToCurry { + + /* + Implementation notes: + - calls static method to avoid binding "this" + - tests the performance of gradually curried methods, hoping for compiler to optimize + - arguments are volatile, to break optimistic CSE happening before the actual call + - using invokeExact and Integers to skip argument conversions + - baseline includes calling the method directly, and this is known to be super-fast due to inlining + */ + + private MethodHandle mhOrig; + private MethodHandle mhCurry1; + private MethodHandle mhCurry2; + private MethodHandle mhCurry3; + + private volatile Integer arg1 = 1; + private volatile Integer arg2 = 2; + private volatile Integer arg3 = 3; + + @Setup + public void setup() throws Throwable { + mhOrig = MethodHandles.lookup().findStatic(MethodHandleBindToCurry.class, "doWork", + MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + mhCurry1 = mhOrig.bindTo(arg1); + mhCurry2 = mhCurry1.bindTo(arg2); + mhCurry3 = mhCurry2.bindTo(arg3); + } + + @Benchmark + public int baselineRaw() { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoke_C0() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoke_C1() throws Throwable { + return (int) mhCurry1.invokeExact(arg2, arg3); + } + + @Benchmark + public int testInvoke_C2() throws Throwable { + return (int) mhCurry2.invokeExact(arg3); + } + + @Benchmark + public int testInvoke_C3() throws Throwable { + return (int) mhCurry3.invokeExact(); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks autoboxing conversion. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertBoxing { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling static method as to minimize virtual dispatch overheads. + */ + + private Integer valueBoxed; + private int valueUnboxed; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findStatic(MethodHandleConvertBoxing.class, "target", MethodType.methodType(int.class, int.class)); + newType = MethodType.methodType(int.class, Integer.class); + valueBoxed = 42; + valueUnboxed = 42; + } + + @Benchmark + public int baselineExact() throws Throwable { + return (int) mh.invokeExact(valueUnboxed); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(int.class, Integer.class)); + } + + @Benchmark + public int test_3_Call() throws Throwable { + return (int) mh.invoke(valueBoxed); + } + + public static int target(int value) { + return value + 1; + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the casts are applied. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertCast { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling static method as to minimize virtual dispatch overheads. + */ + + private A instanceA; + private B instanceB; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findStatic(MethodHandleConvertCast.class, "target", MethodType.methodType(A.class, A.class)); + newType = MethodType.methodType(A.class, B.class); + instanceA = new A(); + instanceB = new B(); + } + + @Benchmark + public A baselineExact() throws Throwable { + return (A) mh.invokeExact(instanceA); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(A.class, B.class)); + } + + @Benchmark + public A test_3_Call() throws Throwable { + return (A) mh.invoke(instanceB); + } + + public static A target(A value) { + return value; + } + + public static class A {} + public static class B extends A { } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the return type conversion: void -> int. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertReturnPrimitive { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling virtual method to guarantee side-effects on value, without trading off scalability. + * This test should be executed in non-shared mode. + */ + + public int value; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findVirtual(MethodHandleConvertReturnPrimitive.class, "target", MethodType.methodType(void.class)); + newType = MethodType.methodType(int.class, MethodHandleConvertReturnPrimitive.class); + } + + @Benchmark + public void baselineExact() throws Throwable { + mh.invokeExact(this); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(int.class, MethodHandleConvertReturnPrimitive.class)); + } + + @Benchmark + public int test_3_Call() throws Throwable { + return (int) mh.invoke(this); + } + + public void target() { + value++; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the return type conversion: void -> Integer. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertReturnReference { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling virtual method to guarantee side-effects on value, without trading off scalability. + * This test should be executed in non-shared mode. + */ + + public int value; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findVirtual(MethodHandleConvertReturnReference.class, "target", MethodType.methodType(void.class)); + newType = MethodType.methodType(Integer.class, MethodHandleConvertReturnReference.class); + } + + @Benchmark + public void baselineExact() throws Throwable { + mh.invokeExact(this); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(Integer.class, MethodHandleConvertReturnReference.class)); + } + + @Benchmark + public Object test_3_Call() throws Throwable { + return mh.invoke(this); + } + + public void target() { + value++; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the return type conversion: int -> void. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertReturnVoid { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling virtual method to guarantee side-effects on value, without trading off scalability. + * This test should be executed in non-shared mode. + */ + + public int value; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findVirtual(MethodHandleConvertReturnVoid.class, "target", MethodType.methodType(int.class)); + newType = MethodType.methodType(void.class, MethodHandleConvertReturnVoid.class); + } + + @Benchmark + public int baselineExact() throws Throwable { + return (int) mh.invokeExact(this); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(void.class, MethodHandleConvertReturnVoid.class)); + } + + @Benchmark + public void test_3_Call() throws Throwable { + mh.invoke(this); + } + + public int target() { + return value++; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the unboxing conversion. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertUnboxing { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling static method as to minimize virtual dispatch overheads. + */ + + private Integer valueBoxed; + private int valueUnboxed; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findStatic(MethodHandleConvertUnboxing.class, "target", MethodType.methodType(int.class, Integer.class)); + newType = MethodType.methodType(int.class, int.class); + valueBoxed = 42; + valueUnboxed = 42; + } + + @Benchmark + public int baselineExact() throws Throwable { + return (int) mh.invokeExact(valueBoxed); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(int.class, int.class)); + } + + @Benchmark + public int test_3_Call() throws Throwable { + return (int) mh.invoke(valueUnboxed); + } + + public static int target(Integer value) { + return value + 1; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses runtime argument conversion performance for MethodHandles. + * This particular test checks the widening conversion. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleConvertWidening { + + /* + * Implementation notes: + * + * Baseline is invokeExact call, which presumably measures the performance without argument conversion. + * + * The test is subdivided into three subtests, gradually doing more work: + * - 1_Convert: calls MH.asType to do actual conversion + * - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion + * - 3_Call: calls MH.invoke, requesting argument conversion + * + * Calling static method as to minimize virtual dispatch overheads. + */ + + private long valueLong; + private int valueInt; + + private MethodHandle mh; + private MethodType newType; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findStatic(MethodHandleConvertWidening.class, "target", MethodType.methodType(long.class, long.class)); + newType = MethodType.methodType(long.class, int.class); + valueInt = 42; + valueLong = 42L; + } + + @Benchmark + public long baselineExact() throws Throwable { + return (long) mh.invokeExact(valueLong); + } + + @Benchmark + public MethodHandle test_1_Convert() throws Throwable { + return mh.asType(newType); + } + + @Benchmark + public MethodHandle test_2_MTConvert() throws Throwable { + return mh.asType(MethodType.methodType(long.class, int.class)); + } + + @Benchmark + public long test_3_Call() throws Throwable { + return (long) mh.invoke(valueInt); + } + + public static long target(long value) { + return value + 1; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark to assess basic MethodHandle performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleInvokeWithArgs { + + /* + * Implementation notes: + * - this is a very basic test, does not do any parameter conversion (in fact, no parameters at all) + * - baselines include calling method directly, and doing the same via reflection + * - baselineRaw is known to be super-fast with good inlining + */ + + private int i; + private static MethodHandle mh; + + private Integer a = 42; + + @Setup + public void setup() throws Throwable { + mh = MethodHandles.lookup().findVirtual(MethodHandleInvokeWithArgs.class, "doWork", MethodType.methodType(int.class, Integer.class)); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(a); + } + + @Benchmark + public int baselineInvoke() throws Throwable { + return (int) mh.invoke(this, a); + } + + @Benchmark + public int baselineInvokeExact() throws Throwable { + return (int) mh.invokeExact(this, a); + } + + @Benchmark + public int testInvoke_WithArguments() throws Throwable { + return (int) mh.invokeWithArguments(this, a); + } + + public int doWork(Integer a) { + return i += a; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark evaluates the performance of MethodHandleProxies.* + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleProxiesAsIFInstance { + + /** + * Implementation notes: + * - asInterfaceInstance() can only target static MethodHandle (adapters needed to call instance method?) + * - baselineCompute will quickly degrade to GC test, if escape analysis is unable to spare the allocation + * - testCreate* will always be slower if allocation is not eliminated; baselineAllocCompute makes sure allocation is present + */ + + public int i; + + private MethodHandle target; + private Doable precreated; + + @Setup + public void setup() throws Throwable { + target = MethodHandles.lookup().findStatic(MethodHandleProxiesAsIFInstance.class, "doWork", MethodType.methodType(int.class, int.class)); + precreated = MethodHandleProxies.asInterfaceInstance(Doable.class, target); + } + + @Benchmark + public Doable testCreate() { + Doable doable = MethodHandleProxies.asInterfaceInstance(Doable.class, target); + return doable; // make sure allocation happens + } + + @Benchmark + public Doable testCreateCall() { + Doable doable = MethodHandleProxies.asInterfaceInstance(Doable.class, target); + i = doable.doWork(i); // make sure computation happens + return null; // let allocation be eliminated + } + + @Benchmark + public Doable testCall() { + i = precreated.doWork(i); // make sure computation happens + return precreated; + } + + @Benchmark + public Doable baselineCompute() { + Doable doable = new Doable() { + @Override + public int doWork(int i) { + return MethodHandleProxiesAsIFInstance.doWork(i); + } + }; + + i = doable.doWork(i); // make sure computation happens + return null; // let allocation be eliminated + } + + @Benchmark + public Doable baselineAllocCompute() { + Doable doable = new Doable() { + @Override + public int doWork(int i) { + return MethodHandleProxiesAsIFInstance.doWork(i); + } + }; + + i = doable.doWork(i); // make sure computation happens + return doable; // make sure allocation happens + } + + public static int doWork(int i) { + return i + 1; + } + + public interface Doable { + int doWork(int i); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark evaluates the performance of MethodHandleProxies.* supplementary methods. + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandleProxiesSuppl { + + /* + * Implementation notes: + * - This is a very naive test, evaluates the performance of service methods. + */ + + private Doable instance; + + @Setup + public void setup() throws Throwable { + MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleProxiesSuppl.class, "doWork", MethodType.methodType(int.class, int.class)); + instance = MethodHandleProxies.asInterfaceInstance(Doable.class, target); + } + + @Benchmark + public Object baselineReturn() { + return instance; + } + + @Benchmark + public boolean testIsWrapperInstance() { + return MethodHandleProxies.isWrapperInstance(instance); + } + + @Benchmark + public Class testInstanceType() { + return MethodHandleProxies.wrapperInstanceType(instance); + } + + @Benchmark + public MethodHandle testInstanceTarget() { + return MethodHandleProxies.wrapperInstanceTarget(instance); + } + + public static int doWork(int i) { + throw new IllegalStateException("Can't touch this"); + } + + public interface Doable { + int doWork(int i); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the performance of MethodHandles.arrayElementGetter + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandlesArrayElementGetter { + + /** + * Implementation notes: + * - creating simple array, and accessing the middle element + * - might have done iteration over array, but that will measure pipelining effects instead + * - volatile modifier on array breaks the DCE, which would otherwise eliminate the array load + * - the rationale for array size and access pattern is coherent to SetterBench + */ + + private static final int SIZE = 1024; + private static final int POS = SIZE/2; + + private static MethodHandle mh; + private volatile int[] array; + + @Setup + public void setup() throws Throwable { + array = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + array[i] = i; + } + mh = MethodHandles.arrayElementGetter(int[].class); + } + + @Benchmark + public MethodHandle testCreate() { + return MethodHandles.arrayElementGetter(int[].class); + } + + @Benchmark + public int baselineRaw() { + return access(array, POS); + } + + @Benchmark + public int testGetter() throws Throwable { + return (int) mh.invoke(array, POS); + } + + public int access(int[] array, int pos) { + return array[pos]; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the performance of MethodHandles.arrayElementSetter + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandlesArrayElementSetter { + + /** + * Implementation notes: + * - creating simple array, and accessing the middle element + * - might have done iteration over array, but that will measure pipelining effects instead + * - volatile modifier on array breaks the DCE, which would otherwise eliminate the array store + * - the array is not shared to prevent true sharing + * - the array is large enough to prevent false sharing + */ + + private static final int SIZE = 1024; + private static final int POS = SIZE/2; + + private static MethodHandle mh; + private volatile int[] array; + + @Setup + public void setup() throws Throwable { + array = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + array[i] = i; + } + mh = MethodHandles.arrayElementSetter(int[].class); + } + + @Benchmark + public MethodHandle testCreate() { + return MethodHandles.arrayElementSetter(int[].class); + } + + @Benchmark + public void baselineRaw() { + access(array, POS, 1); + } + + @Benchmark + public void testSetter() throws Throwable { + mh.invoke(array, POS, 1); + } + + public void access(int[] array, int pos, int v) { + array[pos] = v; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.catchException() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandlesCatchException { + + /** + * Implementation notes: + * - emulating instance method handles because of current issue with instance methods + * (http://monaco.us.oracle.com/detail.jsf?cr=7179751) + * - exception is cached to harness the MH code, not exception instantiation + * - measuring two modes: a) always going through normal code path; b) always going through exceptional one + * - baselines do the same thing in pure Java + */ + + private static final MyException MY_EXCEPTION = new MyException(); + + private int i1; + private int i2; + + private static MethodHandle methNormal; + private static MethodHandle methExceptional; + + @Setup + public void setup() throws Throwable { + MethodHandle bodyNormal = MethodHandles.lookup().findStatic(MethodHandlesCatchException.class, "doWorkNormal", MethodType.methodType(void.class, MethodHandlesCatchException.class)); + MethodHandle bodyExceptional = MethodHandles.lookup().findStatic(MethodHandlesCatchException.class, "doWorkExceptional", MethodType.methodType(void.class, MethodHandlesCatchException.class)); + MethodHandle fallback = MethodHandles.lookup().findStatic(MethodHandlesCatchException.class, "fallback", MethodType.methodType(void.class, MyException.class, MethodHandlesCatchException.class)); + + methNormal = MethodHandles.catchException(bodyNormal, MyException.class, fallback); + methExceptional = MethodHandles.catchException(bodyExceptional, MyException.class, fallback); + } + + @Benchmark + public void baselineNormal() { + try { + doWorkNormal(this); + } catch (MyException e) { + fallback(e, this); + } + } + + @Benchmark + public void baselineExceptional() { + try { + doWorkExceptional(this); + } catch (MyException e) { + fallback(e, this); + } + } + + @Benchmark + public void testNormal() throws Throwable { + methNormal.invokeExact(this); + } + + @Benchmark + public void testExceptional() throws Throwable { + methExceptional.invokeExact(this); + } + + + public static void doWorkNormal(MethodHandlesCatchException inst) throws MyException { + inst.i1++; + } + + public static void doWorkExceptional(MethodHandlesCatchException inst) throws MyException { + inst.i1++; + throw MY_EXCEPTION; + } + + public static void fallback(MyException ex, MethodHandlesCatchException inst) { + inst.i2++; + } + + public static class MyException extends Exception { + + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.constant() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesConstant { + + private MethodHandle mh; + private Integer cachedInt; + + @Setup + public void setup() { + cachedInt = 42; + mh = MethodHandles.constant(Integer.class, 42); + } + + @Benchmark + public Integer baselineReturn() { + return cachedInt; + } + + @Benchmark + public MethodHandle interCreate() throws Throwable { + return MethodHandles.constant(Integer.class, 42); + } + + @Benchmark + public MethodHandle interCreateCached() throws Throwable { + return MethodHandles.constant(Integer.class, cachedInt); + } + + @Benchmark + public Integer testInvoke() throws Throwable { + return (Integer) mh.invoke(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.dropArguments() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesDropArguments { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + */ + + private MethodHandle orig; + private MethodHandle modified; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + orig = MethodHandles.lookup().findStatic(MethodHandlesDropArguments.class, "doWork", MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + modified = MethodHandles.dropArguments(orig, 0, int.class); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int baselineMH() throws Throwable { + return (int) orig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoke() throws Throwable { + return (int) modified.invokeExact(0, arg1, arg2, arg3); + } + + @Benchmark + public MethodHandle interCreate() throws Throwable { + return MethodHandles.dropArguments(orig, 0, int.class); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.exactInvoker() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesExactInvoker { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + * - tested method should perform no worse than the baseline + */ + + private MethodHandle mhOrig; + private MethodHandle mnInvoke; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + MethodType mt = MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class); + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesInsertArguments.class, "doWork", mt); + mnInvoke = MethodHandles.exactInvoker(mt); + } + + @Benchmark + public int baselineOrig() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoker() throws Throwable { + return (int) mnInvoke.invokeExact(mhOrig, arg1, arg2, arg3); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.filterArguments() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesFilterArgs { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + * - the filter is empty to measure infra costs, not the filter itself + * - baselines should be comparable for each method if optimized enough + */ + + private MethodHandle orig; + private MethodHandle modified1; + private MethodHandle modified2; + private MethodHandle modified3; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + orig = MethodHandles.lookup().findStatic(MethodHandlesFilterArgs.class, "doWork", MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + MethodHandle filter = MethodHandles.lookup().findStatic(MethodHandlesFilterArgs.class, "filter", MethodType.methodType(Integer.class, Integer.class)); + modified1 = MethodHandles.filterArguments(orig, 0, filter); + modified2 = MethodHandles.filterArguments(orig, 0, filter, filter); + modified3 = MethodHandles.filterArguments(orig, 0, filter, filter, filter); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int baselineRawConvert() throws Throwable { + return doWork(filter(arg1), filter(arg2), filter(arg3)); + } + + @Benchmark + public int baselineMH() throws Throwable { + return (int) orig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int baselineMHConvert() throws Throwable { + return (int) orig.invokeExact(filter(arg1), filter(arg2), filter(arg3)); + } + + @Benchmark + public int testInvoke_M1() throws Throwable { + return (int) modified1.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoke_M2() throws Throwable { + return (int) modified2.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoke_M3() throws Throwable { + return (int) modified3.invokeExact(arg1, arg2, arg3); + } + + public static Integer filter(Integer a) { + return a; + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.filterReturnValue() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesFilterReturn { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + */ + + private MethodHandle orig; + private MethodHandle filter; + private MethodHandle modified; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + orig = MethodHandles.lookup().findStatic(MethodHandlesFilterReturn.class, "doWork", MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + filter = MethodHandles.lookup().findStatic(MethodHandlesFilterReturn.class, "filter", MethodType.methodType(int.class, int.class)); + modified = MethodHandles.filterReturnValue(orig, filter); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return filter(doWork(arg1, arg2, arg3)); + } + + @Benchmark + public int baselineMH() throws Throwable { + return filter((int) orig.invokeExact(arg1, arg2, arg3)); + } + + @Benchmark + public int testInvoke() throws Throwable { + return (int) modified.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public MethodHandle interCreate() throws Throwable { + return MethodHandles.filterReturnValue(orig, filter); + } + + public static int filter(int a) { + return a * 2; + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.foldArguments() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesFoldArguments { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + */ + + private MethodHandle mhOrig; + private MethodHandle mhFolded; + private MethodHandle mhTarget; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesFoldArguments.class, "doWork", MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + mhFolded = MethodHandles.lookup().findStatic(MethodHandlesFoldArguments.class, "doWork", MethodType.methodType(int.class, int.class, Integer.class, Integer.class, Integer.class)); + mhTarget = MethodHandles.foldArguments(mhFolded, mhOrig); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Raw() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Folded() throws Throwable { + return (int) mhFolded.invokeExact(0, arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Target() throws Throwable { + return (int) mhTarget.invokeExact(arg1, arg2, arg3); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + + public static int doWork(int r, Integer a, Integer b, Integer c) { + return r; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.guardWithTest() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodHandlesGuardWithTest { + + /** + * Implementation notes: + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + * - tested method should perform no worse than the baseline + */ + + private MethodHandle mhWork1; + private MethodHandle mhWork2; + private MethodHandle guard; + private boolean choice; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + MethodType mt = MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class); + mhWork1 = MethodHandles.lookup().findVirtual(MethodHandlesGuardWithTest.class, "doWork1", mt); + mhWork2 = MethodHandles.lookup().findVirtual(MethodHandlesGuardWithTest.class, "doWork2", mt); + + MethodHandle chooser = MethodHandles.lookup().findVirtual(MethodHandlesGuardWithTest.class, "chooser", MethodType.methodType(boolean.class)); + guard = MethodHandles.guardWithTest(chooser, mhWork1, mhWork2); + } + + @Benchmark + public int baselineManual() throws Throwable { + if (choice) { + return (int) mhWork1.invokeExact(this, arg1, arg2, arg3); + } else { + return (int) mhWork2.invokeExact(this, arg1, arg2, arg3); + } + } + + @Benchmark + public int testInvoke() throws Throwable { + return (int) guard.invoke(this, arg1, arg2, arg3); + } + + public boolean chooser() { + choice = !choice; + return choice; + } + + public int doWork1(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + + public int doWork2(Integer a, Integer b, Integer c) { + return 31*(31*(31*c + b) + a); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.identity() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesIdentity { + + private MethodHandle mh; + private Object cachedArg; + + @Setup + public void setup() { + cachedArg = new Object(); + mh = MethodHandles.identity(Object.class); + } + + @Benchmark + public Object baselineRaw() throws Throwable { + return new Object(); + } + + @Benchmark + public Object baselineRawCached() throws Throwable { + return cachedArg; + } + + @Benchmark + public Object testInvoke() throws Throwable { + return mh.invoke(new Object()); + } + + @Benchmark + public Object testInvokeCached() throws Throwable { + return mh.invoke(cachedArg); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.insertArguments() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesInsertArguments { + + /** + * Implementation notes: + * - this test is similar to MethodHandleBindToCurryBench + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + */ + + private MethodHandle mhOrig; + private MethodHandle mhCurry1; + private MethodHandle mhCurry2; + private MethodHandle mhCurry3; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesInsertArguments.class, "doWork", MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class)); + mhCurry1 = MethodHandles.insertArguments(mhOrig, 0, arg1); + mhCurry2 = MethodHandles.insertArguments(mhOrig, 0, arg1, arg2); + mhCurry3 = MethodHandles.insertArguments(mhOrig, 0, arg1, arg2, arg3); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_C0() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_C1() throws Throwable { + return (int) mhCurry1.invokeExact(arg2, arg3); + } + + @Benchmark + public int invoke_C2() throws Throwable { + return (int) mhCurry2.invokeExact(arg3); + } + + @Benchmark + public int invoke_C3() throws Throwable { + return (int) mhCurry3.invokeExact(); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.invoker() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesInvoker { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + * - tested method should perform no worse than the baseline + */ + + private MethodHandle mhOrig; + private MethodHandle mnInvoke; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + MethodType mt = MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class); + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesInsertArguments.class, "doWork", mt); + mnInvoke = MethodHandles.invoker(mt); + } + + @Benchmark + public int baselineOrig() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoker() throws Throwable { + return (int) mnInvoke.invokeExact(mhOrig, arg1, arg2, arg3); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.permuteArguments() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesPermuteArguments { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + */ + + private MethodHandle mhOrig; + private MethodHandle mhNoReorder; + private MethodHandle mhReverse; + private MethodHandle mhShift; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + + @Setup + public void setup() throws Throwable { + MethodType mt = MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class); + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesPermuteArguments.class, "doWork", mt); + mhNoReorder = MethodHandles.permuteArguments(mhOrig, mt, 0, 1, 2); + mhReverse = MethodHandles.permuteArguments(mhOrig, mt, 2, 1, 0); + mhShift = MethodHandles.permuteArguments(mhOrig, mt, 2, 0, 1); + } + + @Benchmark + public int baselineRaw() throws Throwable { + return doWork(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Raw() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_NoReorder() throws Throwable { + return (int) mhNoReorder.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Reverse() throws Throwable { + return (int) mhReverse.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int invoke_Shift() throws Throwable { + return (int) mhShift.invokeExact(arg1, arg2, arg3); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.spreadInvoker() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesSpreadInvoker { + + /** + * Implementation notes: + * - calling static method to have consistent arg list without receiver type + * - using volatile ints as arguments to prevent opportunistic optimizations + * - using Integers to limit argument conversion costs + * - tested method should perform no worse than the baseline + */ + + private MethodHandle mhOrig; + private MethodHandle mnInvoke; + + private volatile Integer arg1 = 42; + private volatile Integer arg2 = 43; + private volatile Integer arg3 = 44; + private Object[] cachedArgs; + + @Setup + public void setup() throws Throwable { + cachedArgs = new Integer[]{arg1, arg2, arg3}; + + MethodType mt = MethodType.methodType(int.class, Integer.class, Integer.class, Integer.class); + mhOrig = MethodHandles.lookup().findStatic(MethodHandlesInsertArguments.class, "doWork", mt); + mnInvoke = MethodHandles.spreadInvoker(mt, 0); + } + + @Benchmark + public int baselineOrig() throws Throwable { + return (int) mhOrig.invokeExact(arg1, arg2, arg3); + } + + @Benchmark + public int testInvoker() throws Throwable { + return (int) mnInvoke.invokeExact(mhOrig, new Object[] { arg1, arg2, arg3 }); + } + + @Benchmark + public int testInvokerCached() throws Throwable { + return (int) mnInvoke.invokeExact(mhOrig, cachedArgs); + } + + public static int doWork(Integer a, Integer b, Integer c) { + return 31*(31*(31*a + b) + c); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses MethodHandles.throwException() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodHandlesThrowException { + + /** + * Implementation notes: + * - exceptions have a thorough call back to benchmark instance to prevent elimination (against dumb JITs) + * - testing in plain and cached modes + * - baselines do the same thing, but in pure Java + */ + + public int flag; + private MethodHandle mh; + private MyException cachedException; + + @Setup + public void setup() { + flag = 42; + cachedException = new MyException(); + mh = MethodHandles.throwException(void.class, MyException.class); + } + + @Benchmark + public int baselineRaw() { + try { + throw new MyException(); + } catch (MyException my) { + return my.getFlag(); + } + } + + @Benchmark + public int baselineRawCached() { + try { + throw cachedException; + } catch (MyException my) { + return my.getFlag(); + } + } + + @Benchmark + public int testInvoke() throws Throwable { + try { + mh.invoke(new MyException()); + throw new IllegalStateException("Should throw exception"); + } catch (MyException my) { + return my.getFlag(); + } + } + + @Benchmark + public int testInvokeCached() throws Throwable { + try { + mh.invoke(cachedException); + throw new IllegalStateException("Should throw exception"); + } catch (MyException my) { + return my.getFlag(); + } + } + + @Benchmark + public MethodHandle interCreate() { + return MethodHandles.throwException(void.class, MyException.class); + } + + public class MyException extends Exception { + + public int getFlag() { + return flag; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Assesses general MethodType performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeAcquire { + + private MethodType pTypes; + + @Setup + public void setup() { + pTypes = MethodType.methodType(A.class, B.class); + } + + @Benchmark + public MethodType baselineRaw() { + return pTypes; + } + + @Benchmark + public MethodType testReturnVoid() { + return MethodType.methodType(void.class); + } + + @Benchmark + public MethodType testReturnInt() { + return MethodType.methodType(int.class); + } + + @Benchmark + public MethodType testReturnObject() { + return MethodType.methodType(Object.class); + } + + @Benchmark + public MethodType testSinglePType() { + return MethodType.methodType(void.class, int.class); + } + + @Benchmark + public MethodType testMultiPType() { + return MethodType.methodType(void.class, A.class, B.class); + } + + @Benchmark + public MethodType testMultiPType_Arg() { + return MethodType.methodType(void.class, pTypes); + } + + public static class A {} + public static class B {} + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.appendParameterTypes() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeAppendParams { + + /** + * Implementation notes: + * - tests multiple cases, gradually appending more arguments + * - baselines include just returning the same method type, and calling with empty argument list + */ + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType baselineNop() { + return mt.appendParameterTypes(); + } + + @Benchmark + public MethodType test_A1() { + return mt.appendParameterTypes(int.class); + } + + @Benchmark + public MethodType test_A2() { + return mt.appendParameterTypes(int.class, int.class); + } + + @Benchmark + public MethodType test_A3() { + return mt.appendParameterTypes(int.class, int.class, int.class); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.changeParameterType() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeChangeParam { + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class, int.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType baselineSame() { + return mt.changeParameterType(1, int.class); + } + + @Benchmark + public MethodType testChangeType() { + return mt.changeParameterType(1, Integer.class); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.changeReturnType() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeChangeReturn { + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class, int.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType baselineSame() { + return mt.changeReturnType(void.class); + } + + @Benchmark + public MethodType testChange() { + return mt.changeReturnType(Integer.class); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.dropParameterTypes() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeDropParams { + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class, int.class, int.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType baselineSame() { + return mt.dropParameterTypes(0, 0); + } + + @Benchmark + public MethodType testDrop_A1() { + return mt.dropParameterTypes(0, 1); + } + + @Benchmark + public MethodType testDrop_A2() { + return mt.dropParameterTypes(0, 2); + } + + @Benchmark + public MethodType testDrop_A3() { + return mt.dropParameterTypes(0, 3); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.erase() performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeGenerify { + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class, Integer.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType testGeneric() { + return mt.generic(); + } + + @Benchmark + public MethodType testWrapErase() { + return mt.wrap().erase(); + } + + @Benchmark + public MethodType testErase() { + return mt.erase(); + } + + @Benchmark + public MethodType testWrap() { + return mt.wrap(); + } + + @Benchmark + public MethodType testUnwrap() { + return mt.unwrap(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses the MethodType.insertParameterTypes() + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class MethodTypeInsertParams { + + private MethodType mt; + + @Setup + public void setup() { + mt = MethodType.methodType(void.class, int.class); + } + + @Benchmark + public MethodType baselineRaw() { + return mt; + } + + @Benchmark + public MethodType baselineSame() { + return mt.insertParameterTypes(0); + } + + @Benchmark + public MethodType testInsert_A1() { + return mt.insertParameterTypes(0, int.class); + } + + @Benchmark + public MethodType testInsert_A2() { + return mt.insertParameterTypes(0, int.class, int.class); + } + + @Benchmark + public MethodType testInsert_A3() { + return mt.insertParameterTypes(0, int.class, int.class, int.class); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.lang.invoke.SwitchPoint; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assessing SwitchPoint performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class SwitchPointAdhoc { + + /* + * Implementation notes: + * - this test asserts SwitchPoint performance in both valid and invalid cases + * - this test does not assert invalidation performance (hard to do with irreversible SwitchPoint) + * - raw baseline gives the idea for MethodHandle invocation cost + * - CS baseline gives the idea for additional dereference cost + */ + + private MethodHandle body1, body2; + private int i; + private java.lang.invoke.SwitchPoint sw1, sw2; + private CallSite cs; + + @Setup + public void setup() throws NoSuchMethodException, IllegalAccessException { + sw1 = new java.lang.invoke.SwitchPoint(); + sw2 = new java.lang.invoke.SwitchPoint(); + SwitchPoint.invalidateAll(new SwitchPoint[]{sw2}); + body1 = MethodHandles.lookup().findVirtual(SwitchPointAdhoc.class, "body1", MethodType.methodType(int.class, int.class)); + body2 = MethodHandles.lookup().findVirtual(SwitchPointAdhoc.class, "body2", MethodType.methodType(int.class, int.class)); + cs = new MutableCallSite(body1); + } + + @Benchmark + public void baselineRaw() throws Throwable { + i = (int) body1.invoke(this, i); + } + + @Benchmark + public void baselineCS() throws Throwable { + i = (int) cs.getTarget().invoke(this, i); + } + + @Benchmark + public void testValid() throws Throwable { + MethodHandle handle = sw1.guardWithTest(body1, body2); + i = (int) handle.invoke(this, i); + } + + @Benchmark + public void testInvalid() throws Throwable { + MethodHandle handle = sw2.guardWithTest(body1, body2); + i = (int) handle.invoke(this, i); + } + + public int body1(int i) { + return i + 1; + } + + public int body2(int i) { + return i + 1; + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java b/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.invoke.*; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assessing SwitchPoint performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class SwitchPointGuard { + + /* + * Implementation notes: + * - this test asserts SwitchPoint performance in both valid and invalid cases + * - this test does not assert invalidation performance (hard to do with irreversible SwitchPoint) + * - raw baseline gives the idea for MethodHandle invocation cost + * - CS baseline gives the idea for additional dereference cost + */ + + private MethodHandle body1, body2; + private int i; + private SwitchPoint sw1, sw2; + private CallSite cs; + private MethodHandle guard1, guard2; + + @Setup + public void setup() throws NoSuchMethodException, IllegalAccessException { + sw1 = new SwitchPoint(); + sw2 = new SwitchPoint(); + SwitchPoint.invalidateAll(new SwitchPoint[]{sw2}); + body1 = MethodHandles.lookup().findVirtual(SwitchPointGuard.class, "body1", MethodType.methodType(int.class, int.class)); + body2 = MethodHandles.lookup().findVirtual(SwitchPointGuard.class, "body2", MethodType.methodType(int.class, int.class)); + guard1 = sw1.guardWithTest(body1, body2); + guard2 = sw2.guardWithTest(body1, body2); + cs = new MutableCallSite(body1); + } + + @Benchmark + public void baselineRaw() throws Throwable { + i = (int) body1.invoke(this, i); + } + + @Benchmark + public void baselineCS() throws Throwable { + i = (int) cs.getTarget().invoke(this, i); + } + + @Benchmark + public void testValid() throws Throwable { + i = (int) guard1.invoke(this, i); + } + + @Benchmark + public void testInvalid() throws Throwable { + i = (int) guard2.invoke(this, i); + } + + public int body1(int i) { + return i + 1; + } + + public int body2(int i) { + return i + 1; + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/lang/reflect/MethodInvoke.java b/test/micro/classes/org/openjdk/bench/java/lang/reflect/MethodInvoke.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/lang/reflect/MethodInvoke.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.reflect; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring java.lang.reflect.Method.invoke speed. + *

+ * TODO: Add tests for virtual and interface methods. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class MethodInvoke { + + private Method staticMeth_0; + private Method staticMeth_6ref; + private Method staticMeth_6prim; + + private Object[] args_0; + private Object[] args_6ref; + private Object[] args_6prim; + + @Setup + public void setup() { + args_0 = new Object[]{}; + args_6ref = new Object[]{ new Object(), new Object(), + new Object(), new Object(), new Object(), new Object()}; + args_6prim = new Object[]{ + new Integer(1), new Long(5L), + new Double(5.6d), new Float(23.11f), + Boolean.TRUE, new Character('d') + }; + + staticMeth_0 = getMethodWithName("staticMethodWithoutParams"); + staticMeth_6ref = getMethodWithName("staticMethodWithSixObjectParams"); + staticMeth_6prim = getMethodWithName("staticMethodWithSixPrimitiveParams"); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public static void staticMethodWithoutParams() { + // intentionally left blank + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public static void staticMethodWithSixObjectParams(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) { + // intentionally left blank + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public static void staticMethodWithSixPrimitiveParams(int i, long j, double d, float f, boolean z, char c) { + // intentionally left blank + } + + /* inner method to get the method to invoke. */ + + private static Method getMethodWithName(String methodName) { + Method[] methodArray = MethodInvoke.class.getMethods(); + for (Method m : methodArray) { + if (m.getName().equals(methodName)) { + return m; + } + } + return null; + } + + @Benchmark + public void invokeWithoutParams() throws InvocationTargetException, IllegalAccessException { + staticMeth_0.invoke(null, args_0); + } + + @Benchmark + public void invokeWithSixObjectParams() throws Exception { + staticMeth_6ref.invoke(null, args_6ref); + } + + @Benchmark + public void invokeWithSixPrimitiveParams() throws Exception { + staticMeth_6prim.invoke(null, args_6prim); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/math/BigDecimals.java b/test/micro/classes/org/openjdk/bench/java/math/BigDecimals.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/math/BigDecimals.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.math; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.math.BigDecimal; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class BigDecimals { + + /** Make sure TEST_SIZE is used to size the arrays. We need this constant to parametrize the operations count. */ + private static final int TEST_SIZE = 100; + + /* dummy variables for intermediate results */ + public Object[] dummyArr; + public String[] dummyStringArray; + public int dummy; + + /* array to hold the created objects. */ + private BigDecimal[] bigDecimals; + private String[] stringInputs; + private double[] doubleInputs; + private BigDecimal[] hugeArray, largeArray, smallArray; + + @Setup + public void setup() { + Random r = new Random(1123); + dummyArr = new Object[TEST_SIZE]; + bigDecimals = new BigDecimal[TEST_SIZE]; + stringInputs = new String[TEST_SIZE]; + doubleInputs = new double[TEST_SIZE]; + for (int i = 0; i < TEST_SIZE; i++) { + double value = (double) (i + 1); + switch (i % 4) { + case 0: + value = -value * 54345.0d; + break; + case 1: + value = value * 5434543453454355e100; + break; + case 2: + value = -value / 5434543453454355e100; + break; + case 3: + break; + } + + bigDecimals[i] = new BigDecimal(value); + stringInputs[i] = "" + value; + doubleInputs[i] = value; + } + + /* + * Huge numbers larger than MAX_LONG + */ + hugeArray = new BigDecimal[TEST_SIZE]; + + /* + * Large numbers less than MAX_LONG but larger than MAX_INT + */ + largeArray = new BigDecimal[TEST_SIZE]; + + /* + * Small number less than MAX_INT + */ + smallArray = new BigDecimal[TEST_SIZE]; + + dummyStringArray = new String[TEST_SIZE]; + for (int i = 0; i < TEST_SIZE; i++) { + int value = Math.abs(r.nextInt()); + hugeArray[i] = new BigDecimal("" + ((long) value + (long) Integer.MAX_VALUE) + + ((long) value + (long) Integer.MAX_VALUE) + ".55"); + largeArray[i] = new BigDecimal("" + ((long) value + (long) Integer.MAX_VALUE) + ".55"); + smallArray[i] = new BigDecimal("" + ((long) value / 1000) + ".55"); + } + } + + /** Invokes the (String)-constructor of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testConstructorWithString(Blackhole bh) { + for (String s : stringInputs) { + bh.consume(new BigDecimal(s)); + } + } + + /** Invokes the (double)-constructor of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testConstructorWithDouble(Blackhole bh) { + for (double s : doubleInputs) { + bh.consume(new BigDecimal(s)); + } + } + + /** Invokes the toString method of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testToString(Blackhole bh) { + for (BigDecimal s : bigDecimals) { + bh.consume(s.toString()); + } + } + + /** + * Invokes the setScale method of BigDecimal with various different values. + */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testSetScale(Blackhole bh) { + for (BigDecimal s : bigDecimals) { + bh.consume(s.setScale(2, BigDecimal.ROUND_HALF_UP)); + } + } + + /** Invokes the setScale method of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(50 * TEST_SIZE) + public void testSetScaleVarious(Blackhole bh) { + for (int scale = 0; scale < 50; scale++) { + for (BigDecimal s : bigDecimals) { + bh.consume(s.setScale(scale, BigDecimal.ROUND_HALF_UP)); + } + } + } + + /** Invokes the add method of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testAdd(Blackhole bh) { + BigDecimal tmp = null; + for (BigDecimal s : bigDecimals) { + if (tmp == null) { + tmp = s; + continue; + } + tmp = tmp.add(s); + } + bh.consume(tmp); + } + + /** Invokes the multiply method of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testMultiply(Blackhole bh) { + BigDecimal tmp = null; + for (BigDecimal s : bigDecimals) { + if (tmp == null) { + tmp = s; + continue; + } + tmp = tmp.multiply(s); + } + bh.consume(tmp); + } + + /** Invokes the compareTo method of BigDecimal with various different values. */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE - 1) + public void testCompareTo(Blackhole bh) { + BigDecimal c = bigDecimals[0]; + for (BigDecimal s : bigDecimals) { + bh.consume(c.compareTo(s)); + } + } + + /** Test BigDecimal.toString() with huge numbers larger than MAX_LONG */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testHugeToString(Blackhole bh) { + for (BigDecimal s : hugeArray) { + bh.consume(s.toString()); + } + } + + /** Test BigDecimal.toString() with large numbers less than MAX_LONG but larger than MAX_INT */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testLargeToString(Blackhole bh) { + for (BigDecimal s : largeArray) { + bh.consume(s.toString()); + } + } + + /** Test BigDecimal.toString() with small numbers less than MAX_INT */ + @Benchmark + @OperationsPerInvocation(TEST_SIZE) + public void testSmallToString(Blackhole bh) { + for (BigDecimal s : smallArray) { + bh.consume(s.toString()); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/math/BigIntegers.java b/test/micro/classes/org/openjdk/bench/java/math/BigIntegers.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/math/BigIntegers.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.openjdk.bench.java.math; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.math.BigInteger; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class BigIntegers { + + private BigInteger[] hugeArray, largeArray, smallArray; + public String[] dummyStringArray; + public Object[] dummyArr; + private static final int TESTSIZE = 1000; + + @Setup + public void setup() { + Random r = new Random(1123); + + hugeArray = new BigInteger[TESTSIZE]; /* + * Huge numbers larger than + * MAX_LONG + */ + largeArray = new BigInteger[TESTSIZE]; /* + * Large numbers less than + * MAX_LONG but larger than + * MAX_INT + */ + smallArray = new BigInteger[TESTSIZE]; /* + * Small number less than + * MAX_INT + */ + + dummyStringArray = new String[TESTSIZE]; + dummyArr = new Object[TESTSIZE]; + + for (int i = 0; i < TESTSIZE; i++) { + int value = Math.abs(r.nextInt()); + + hugeArray[i] = new BigInteger("" + ((long) value + (long) Integer.MAX_VALUE) + + ((long) value + (long) Integer.MAX_VALUE)); + largeArray[i] = new BigInteger("" + ((long) value + (long) Integer.MAX_VALUE)); + smallArray[i] = new BigInteger("" + ((long) value / 1000)); + } + } + + /** Test BigInteger.toString() with huge numbers larger than MAX_LONG */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testHugeToString(Blackhole bh) { + for (BigInteger s : hugeArray) { + bh.consume(s.toString()); + } + } + + /** Test BigInteger.toString() with large numbers less than MAX_LONG but larger than MAX_INT */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testLargeToString(Blackhole bh) { + for (BigInteger s : largeArray) { + bh.consume(s.toString()); + } + } + + /** Test BigInteger.toString() with small numbers less than MAX_INT */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testSmallToString(Blackhole bh) { + for (BigInteger s : smallArray) { + bh.consume(s.toString()); + } + } + + /** Invokes the multiply method of BigInteger with various different values. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testMultiply(Blackhole bh) { + BigInteger tmp = null; + for (BigInteger s : hugeArray) { + if (tmp == null) { + tmp = s; + continue; + } + tmp = tmp.multiply(s); + } + bh.consume(tmp); + } + + /** Invokes the multiply method of BigInteger with various different values. */ + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public void testAdd(Blackhole bh) { + BigInteger tmp = null; + for (BigInteger s : hugeArray) { + if (tmp == null) { + tmp = s; + continue; + } + tmp = tmp.add(s); + } + bh.consume(tmp); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/net/DatagramSocketTest.java b/test/micro/classes/org/openjdk/bench/java/net/DatagramSocketTest.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/net/DatagramSocketTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.concurrent.TimeUnit; + +/** + * DatagramSocket micros designed to stress UDP performance. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class DatagramSocketTest { + + @Param({"1024", "2048", "4096", "8192", "16384", "32768"}) + int size; + + private DatagramSocket socket; + private DatagramPacket packet; + + @Setup + public void prepare() throws SocketException, UnknownHostException { + socket = new DatagramSocket(); + + byte[] buf = new byte[size]; + packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("localhost"), 9877); + } + + @TearDown + public void cleanup() { + socket.close(); + } + + @Benchmark + public void testSend() throws IOException { + socket.send(packet); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/net/SocketChannelReadWrite.java b/test/micro/classes/org/openjdk/bench/java/net/SocketChannelReadWrite.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/net/SocketChannelReadWrite.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on network conditions and paltform. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class SocketChannelReadWrite { + + private ServerSocketChannel ssc; + private SocketChannel s1, s2; + private ReadThread rt; + private ByteBuffer bb = ByteBuffer.allocate(1); + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + InetAddress iaddr = InetAddress.getLocalHost(); + + ssc = ServerSocketChannel.open().bind(null); + s1 = SocketChannel.open(new InetSocketAddress(iaddr, ssc.socket().getLocalPort())); + s2 = ssc.accept(); + + rt = new ReadThread(s2); + rt.start(); + + bb.put((byte) 47); + bb.flip(); + } + + @TearDown(Level.Trial) + public void afterRun() throws IOException, InterruptedException { + s1.close(); + s2.close(); + ssc.close(); + rt.join(); + } + + @Benchmark + public void test() throws IOException { + s1.write(bb); + bb.flip(); + } + + static class ReadThread extends Thread { + private SocketChannel sc; + + public ReadThread(SocketChannel s2) { + this.sc = s2; + } + + public void run() { + try { + ByteBuffer bb = ByteBuffer.allocate(1); + while (sc.read(bb) > 0) { + bb.flip(); + } + } catch (ClosedChannelException ex) { + // shutdown time + } catch (IOException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/net/SocketReadWrite.java b/test/micro/classes/org/openjdk/bench/java/net/SocketReadWrite.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/net/SocketReadWrite.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +/** + * Tests the overheads of I/O API. + * This test is known to depend heavily on network conditions and paltform. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class SocketReadWrite { + + private OutputStream os; + private InputStream is; + private ServerSocket ss; + private Socket s1, s2; + private ReadThread rt; + + @Setup + public void beforeRun() throws IOException { + InetAddress iaddr = InetAddress.getLocalHost(); + + ss = new ServerSocket(0); + s1 = new Socket(iaddr, ss.getLocalPort()); + s2 = ss.accept(); + + os = s1.getOutputStream(); + is = s2.getInputStream(); + + rt = new ReadThread(is); + rt.start(); + } + + @TearDown + public void afterRun() throws IOException, InterruptedException { + os.write(0); + os.close(); + is.close(); + s1.close(); + s2.close(); + ss.close(); + rt.join(); + } + + @Benchmark + public void test() throws IOException { + os.write((byte) 4711); + } + + static class ReadThread extends Thread { + private InputStream is; + + public ReadThread(InputStream is) { + this.is = is; + } + + public void run() { + try { + while (is.read() > 0); + } catch (SocketException ex) { + // ignore - most likely "socket closed", which means shutdown + } catch (IOException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/net/SocketStreaming.java b/test/micro/classes/org/openjdk/bench/java/net/SocketStreaming.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/net/SocketStreaming.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.TimeUnit; + +/** + * Micro benchmark for streaming data over a Socket. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class SocketStreaming { + + /** The bytes to write/read. */ + public static final int dataLength = 16383; + /** setTcpNoDelay(noNagle) */ + public static final boolean noNagle = false; + + private WriterThread writerThread; + private Socket readSocket; + private byte[] bytes; + + @Setup + public void prepare() throws Exception { + bytes = new byte[dataLength]; + + // Setup the writer thread + writerThread = new WriterThread(dataLength, noNagle); + writerThread.start(); + + // Wait for a read socket + readSocket = writerThread.waitForReadSocket(); + } + + @TearDown + public void cleanup() throws IOException { + // Take down the writer thread and the reader socket + writerThread.finish(); + while (!readSocket.isClosed()) { + readSocket.close(); + } + readSocket = null; + } + + @Benchmark + public void testSocketInputStreamRead() throws InterruptedException, IOException { + InputStream in = readSocket.getInputStream(); + + // Notify the writer thread to add elements to stream + writerThread.requestSendBytes(); + + // Read these from the stream + int bytesRead = 0; + while (bytesRead < dataLength) { + int lastRead = in.read(bytes); + if (lastRead < 0) { + throw new InternalError("Unexpectedly got " + lastRead + " bytes from the socket"); + } + bytesRead += lastRead; + } + } + + /** + * Thread used to write bytes to a socket. + */ + private class WriterThread extends Thread { + + /** The number of bytes to write. */ + private int dataLength; + /** setTcpNoDelay(noNagle) */ + private boolean noNagle; + /** Lock needed to send sendBytes requests. */ + private final Object sendBytesLock = new Object(); + /** Indicates that a sendBytes has been requested. */ + private boolean sendBytesRequested; + /** Indicates that no more sendBytes will be requested. Time to shutdown. */ + private boolean sendBytesDone; + /** Lock needed to protect the connectPort variable. */ + private final Object connectLock = new Object(); + /** The port the read socket should connect to. */ + private int connectPort = -1; + + /** + * Constructor. + * + * @param dataLength The number of bytes to write + * @param noNagle setTcpNoDelay(noNagle) + */ + public WriterThread(int dataLength, boolean noNagle) { + super("Load producer"); + this.dataLength = dataLength; + this.noNagle = noNagle; + } + + /** Entry point for data sending helper thread. */ + @Override + public void run() { + try { + Socket writeSocket; + ServerSocket serverSocket = new ServerSocket(0); + + /* Tell the other thread that we now know the port number. + * The other thread will now start to connect until the following accept() call succeeds. + */ + synchronized (connectLock) { + connectPort = serverSocket.getLocalPort(); + connectLock.notify(); + } + + // Wait for the other thread to connect + writeSocket = serverSocket.accept(); + writeSocket.setTcpNoDelay(noNagle); + + // No more connects so this can be closed + serverSocket.close(); + serverSocket = null; + + OutputStream out = writeSocket.getOutputStream(); + + // Iterate as long as sendBytes are issued + while (waitForSendBytesRequest()) { + sendBytes(out); + } + + // Time to shutdown + while (!writeSocket.isClosed()) { + writeSocket.close(); + } + writeSocket = null; + } catch (Exception e) { + System.exit(1); + } + } + + /** + * Sends bytes to the output stream + * + * @param out The output stream + * @throws IOException + */ + private void sendBytes(OutputStream out) throws IOException { + byte outBytes[] = new byte[dataLength]; + + int bytesToSend = dataLength; + int bytesSent = 0; + while (bytesSent < bytesToSend) { + out.write(outBytes); + bytesSent += outBytes.length; + } + } + + /** + * Waits for the readSocket and returns it when it is ready. + * + * @return The socket to read from + * @throws InterruptedException + */ + @SuppressWarnings("SleepWhileHoldingLock") + public Socket waitForReadSocket() throws InterruptedException { + int theConnectPort = waitForConnectPort(); + + while (true) { + try { + return new Socket(InetAddress.getByName(null), theConnectPort); + } catch (IOException e) { + // Wait some more for the server thread to get going + Thread.sleep(1000); + } + } + + } + + /** + * Waits for next sendBytes request + * + * @return true if it is time to sendBytes, false if it is time to shutdown + * @throws InterruptedException + */ + public boolean waitForSendBytesRequest() throws InterruptedException { + synchronized (sendBytesLock) { + while (!sendBytesRequested && !sendBytesDone) { + sendBytesLock.wait(); + } + + // Clear the flag + sendBytesRequested = false; + + return !sendBytesDone; + } + } + + /** Requests a sendBytes. */ + public void requestSendBytes() { + synchronized (sendBytesLock) { + sendBytesRequested = true; + sendBytesLock.notify(); + } + } + + /** Tells the writerThread that it is time to shutdown. */ + public void finish() { + synchronized (sendBytesLock) { + sendBytesDone = true; + sendBytesLock.notify(); + } + } + + private int waitForConnectPort() throws InterruptedException { + synchronized (connectLock) { + while (connectPort == -1) { + connectLock.wait(); + } + return connectPort; + } + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/net/URLEncodeDecode.java b/test/micro/classes/org/openjdk/bench/java/net/URLEncodeDecode.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/net/URLEncodeDecode.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Tests java.net.URLEncoder.encode and Decoder.decode. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class URLEncodeDecode { + + @Param("1024") + public int count; + + @Param("1024") + public int maxLength; + + @Param("3") + public long mySeed; + + public String[] testStringsEncode; + public String[] testStringsDecode; + public String[] toStrings; + + @Setup + public void setupStrings() { + char[] tokens = new char[((int) 'Z' - (int) 'A' + 1) + ((int) 'z' - (int) 'a' + 1) + ((int) '9' - (int) '1' + 1) + 5]; + int n = 0; + tokens[n++] = '0'; + for (int i = (int) '1'; i <= (int) '9'; i++) { + tokens[n++] = (char) i; + } + for (int i = (int) 'A'; i <= (int) 'Z'; i++) { + tokens[n++] = (char) i; + } + for (int i = (int) 'a'; i <= (int) '<'; i++) { + tokens[n++] = (char) i; + } + tokens[n++] = '-'; + tokens[n++] = '_'; + tokens[n++] = '.'; + tokens[n++] = '*'; + + Random r = new Random(mySeed); + testStringsEncode = new String[count]; + testStringsDecode = new String[count]; + toStrings = new String[count]; + for (int i = 0; i < count; i++) { + int l = r.nextInt(maxLength); + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < l; j++) { + int c = r.nextInt(tokens.length); + sb.append(tokens[c]); + } + testStringsEncode[i] = sb.toString(); + } + + for (int i = 0; i < count; i++) { + int l = r.nextInt(maxLength); + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < l; j++) { + int c = r.nextInt(tokens.length + 5); + if (c >= tokens.length) { + sb.append("%").append(tokens[r.nextInt(16)]).append(tokens[r.nextInt(16)]); + } else { + sb.append(tokens[c]); + } + } + testStringsDecode[i] = sb.toString(); + } + } + + @Benchmark + public void testEncodeUTF8(Blackhole bh) throws UnsupportedEncodingException { + for (String s : testStringsEncode) { + bh.consume(java.net.URLEncoder.encode(s, "UTF-8")); + } + } + + @Benchmark + public void testDecodeUTF8(Blackhole bh) throws UnsupportedEncodingException { + for (String s : testStringsDecode) { + bh.consume(URLDecoder.decode(s, "UTF-8")); + } + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/nio/ByteBuffers.java b/test/micro/classes/org/openjdk/bench/java/nio/ByteBuffers.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/nio/ByteBuffers.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.nio; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark operations on java.nio.Buffer. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ByteBuffers { + + @Param({"10", "1000", "100000"}) + private int size; + + public byte dummyByte; + public char dummyChar; + public short dummyShort; + public int dummyInt; + public long dummyLong; + public float dummyFloat; + public double dummyDouble; + + // ---------------- BULK GET TESTS + + @Benchmark + public byte[] testBulkGet() { + return innerBufferBulkGet(ByteBuffer.allocate(size)); + } + + @Benchmark + public byte[] testDirectBulkGet() { + return innerBufferBulkGet(ByteBuffer.allocateDirect(size)); + } + + // ---------------- BULK PUT TESTS + + @Benchmark + public byte[] testBulkPut() { + return innerBufferBulkPut(ByteBuffer.allocate(size)); + } + + @Benchmark + public byte[] testDirectBulkPut() { + return innerBufferBulkPut(ByteBuffer.allocateDirect(size)); + } + + // ---------------- SINGLE GET TESTS + + @Benchmark + public int testSingleGetByte() { + return innerSingleGetByte(ByteBuffer.allocate(1000)); + } + + @Benchmark + public int testSingleGetChar() { + return innerSingleGetChar(ByteBuffer.allocate(1000)); + } + + @Benchmark + public int testSingleGetShort() { + return innerSingleGetShort(ByteBuffer.allocate(1000)); + } + + @Benchmark + public int testSingleGetInt() { + return innerSingleGetInt(ByteBuffer.allocate(1000)); + } + + @Benchmark + public long testSingleGetLong() { + return innerSingleGetLong(ByteBuffer.allocate(1000)); + } + + @Benchmark + public float testSingleGetFloat() { + return innerSingleGetFloat(ByteBuffer.allocate(1000)); + } + + @Benchmark + public double testSingleGetDouble() { + return innerSingleGetDouble(ByteBuffer.allocate(1000)); + } + + @Benchmark + public int testDirectSingleGetByte() { + return innerSingleGetByte(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public int testDirectSingleGetChar() { + return innerSingleGetChar(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public int testDirectSingleGetShort() { + return innerSingleGetShort(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public int testDirectSingleGetInt() { + return innerSingleGetInt(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public long testDirectSingleGetLong() { + return innerSingleGetLong(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public float testDirectSingleGetFloat() { + return innerSingleGetFloat(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public double testDirectSingleGetDouble() { + return innerSingleGetDouble(ByteBuffer.allocateDirect(1000)); + } + + // ---------------- SINGLE PUT TESTS + + @Benchmark + public void testSinglePutByte() { + innerSinglePutByte(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutChar() { + innerSinglePutChar(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutShort() { + innerSinglePutShort(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutInt() { + innerSinglePutInt(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutLong() { + innerSinglePutLong(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutFloat() { + innerSinglePutFloat(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testSinglePutDouble() { + innerSinglePutDouble(ByteBuffer.allocate(1000)); + } + + @Benchmark + public void testDirectSinglePutByte() { + innerSinglePutByte(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutChar() { + innerSinglePutChar(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutShort() { + innerSinglePutShort(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutInt() { + innerSinglePutInt(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutLong() { + innerSinglePutLong(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutFloat() { + innerSinglePutFloat(ByteBuffer.allocateDirect(1000)); + } + + @Benchmark + public void testDirectSinglePutDouble() { + innerSinglePutDouble(ByteBuffer.allocateDirect(1000)); + } + + // ---------------- HELPER METHODS + + private byte[] innerBufferBulkGet(ByteBuffer bb) { + byte[] dummyByteArray = new byte[bb.capacity()]; + bb.get(dummyByteArray); + bb.flip(); + return dummyByteArray; + } + + private byte[] innerBufferBulkPut(ByteBuffer bb) { + byte[] dummyByteArray = new byte[bb.capacity()]; + bb.put(dummyByteArray); + bb.flip(); + return dummyByteArray; + } + + private int innerSingleGetByte(ByteBuffer bb) { + int r = 0; + for (int i = 0; i < bb.capacity(); i++) { + r += bb.get(i); + } + return r; + } + + private int innerSingleGetChar(ByteBuffer bb) { + int r = 0; + for (int i = 0; i < bb.capacity(); i += 2) { + r += bb.getChar(i); + } + return r; + } + + private int innerSingleGetShort(ByteBuffer bb) { + int r = 0; + for (int i = 0; i < bb.capacity(); i += 2) { + r += bb.getShort(i); + } + return r; + } + + private int innerSingleGetInt(ByteBuffer bb) { + int r = 0; + for (int i = 0; i < bb.capacity(); i += 4) { + r += bb.getInt(i); + } + return r; + } + + private long innerSingleGetLong(ByteBuffer bb) { + long r = 0; + for (int i = 0; i < bb.capacity(); i += 8) { + r += bb.getLong(i); + } + return r; + } + + private float innerSingleGetFloat(ByteBuffer bb) { + float r = 0; + for (int i = 0; i < bb.capacity(); i += 4) { + r += bb.getFloat(i); + } + return r; + } + + private double innerSingleGetDouble(ByteBuffer bb) { + double d = 0; + for (int i = 0; i < bb.capacity(); i += 8) { + d += bb.getDouble(i); + } + return d; + } + + private void innerSinglePutByte(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i++) { + bb.put(i, dummyByte); + } + } + + private void innerSinglePutChar(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 2) { + bb.putChar(i, dummyChar); + } + } + + private void innerSinglePutShort(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 2) { + bb.putShort(i, dummyShort); + } + } + + private void innerSinglePutInt(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 4) { + bb.putInt(i, dummyInt); + } + } + + private void innerSinglePutLong(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 8) { + bb.putLong(i, dummyLong); + } + } + + private void innerSinglePutFloat(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 4) { + bb.putFloat(i, dummyFloat); + } + } + + private void innerSinglePutDouble(ByteBuffer bb) { + for (int i = 0; i < bb.capacity(); i += 8) { + bb.putDouble(i, dummyDouble); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/nio/CharsetEncodeDecode.java b/test/micro/classes/org/openjdk/bench/java/nio/CharsetEncodeDecode.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/nio/CharsetEncodeDecode.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.nio; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.util.concurrent.TimeUnit; + +/** + * This benchmark tests the encode/decode loops on different Charsets. It was created from an adhoc benchmark addressing + * a performance issue which in the end boiled down to the encode/decode loops. This is the reason for the values on the + * char and byte arrays. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class CharsetEncodeDecode { + + private byte[] BYTES; + private char[] CHARS; + + private CharsetEncoder encoder; + private CharsetDecoder decoder; + + @Param({"BIG5", "ISO-8859-15", "ASCII", "UTF-16"}) + private String type; + + @Param("16384") + private int size; + + @Setup + public void prepare() { + BYTES = new byte[size]; + CHARS = new char[size]; + for (int i = 0; i < size; ++i) { + int val = 48 + (i % 16); + BYTES[i] = (byte) val; + CHARS[i] = (char) val; + } + + encoder = Charset.forName(type).newEncoder(); + decoder = Charset.forName(type).newDecoder(); + } + + @Benchmark + public ByteBuffer encode() throws CharacterCodingException { + CharBuffer charBuffer = CharBuffer.wrap(CHARS); + return encoder.encode(charBuffer); + } + + @Benchmark + public CharBuffer decode() throws CharacterCodingException { + ByteBuffer byteBuffer = ByteBuffer.wrap(BYTES); + return decoder.decode(byteBuffer); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/security/DoPrivileged.java b/test/micro/classes/org/openjdk/bench/java/security/DoPrivileged.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/security/DoPrivileged.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.security; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring DoPrivileged + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class DoPrivileged { + + private PrivilegedAction privilegedAction; + + @Setup + public void setup() { + privilegedAction = () -> 42; + } + + @Benchmark + public int test() { + return AccessController.doPrivileged(privilegedAction); + } + + @Benchmark + public int testInline() { + return AccessController.doPrivileged((PrivilegedAction) () -> 42); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/security/MessageDigests.java b/test/micro/classes/org/openjdk/bench/java/security/MessageDigests.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/security/MessageDigests.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.security; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Tests various digester algorithms. Sets Fork parameters as these tests are + * rather allocation intensive. Reduced number of forks and iterations as + * benchmarks are stable. + */ +@State(Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +@Fork(jvmArgsAppend = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 5) +public class MessageDigests { + + @Param({"64", "1024", "16384"}) + private int length; + + @Param({"md2", "md5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"}) + private String digesterName; + + @Param({"DEFAULT", "SUN"}) + protected String provider; + + private byte[] inputBytes; + private MessageDigest digester; + + @Setup + public void setup() throws NoSuchAlgorithmException, DigestException, NoSuchProviderException { + inputBytes = new byte[length]; + new Random(1234567890).nextBytes(inputBytes); + if ("DEFAULT".equals(provider)) { + digester = MessageDigest.getInstance(digesterName); + } else { + digester = MessageDigest.getInstance(digesterName, provider); + } + } + + @Benchmark + public byte[] digest() throws DigestException { + return digester.digest(inputBytes); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/ArraysEquals.java b/test/micro/classes/org/openjdk/bench/java/util/ArraysEquals.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/ArraysEquals.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * Tests for Array.equals() with 80 entry arrays differing at beginning, middle, or end. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArraysEquals { + + public char[] testCharArray1 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789a".toCharArray(); + public char[] testCharArray2 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789b".toCharArray(); + public char[] testCharArray3 = "123456789012345678901234567890123456789a123456789012345678901234567890123456789b".toCharArray(); + public char[] testCharArray4 = "1234567890a2345678901234567890123456789a123456789012345678901234567890123456789b".toCharArray(); + public char[] testCharArray5 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789a".toCharArray(); + public byte[] testByteArray1 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789a".getBytes(); + public byte[] testByteArray2 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789b".getBytes(); + public byte[] testByteArray3 = "123456789012345678901234567890123456789a123456789012345678901234567890123456789b".getBytes(); + public byte[] testByteArray4 = "1234567890a2345678901234567890123456789a123456789012345678901234567890123456789b".getBytes(); + public byte[] testByteArray5 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789a".getBytes(); + + /** Char array tests */ + + @Benchmark + public boolean testCharTrue() { + return Arrays.equals(testCharArray1, testCharArray5); + } + + @Benchmark + public boolean testCharFalseEnd() { + return Arrays.equals(testCharArray1, testCharArray2); + } + + @Benchmark + public boolean testCharFalseMid() { + return Arrays.equals(testCharArray1, testCharArray3); + } + + @Benchmark + public boolean testCharFalseBeginning() { + return Arrays.equals(testCharArray1, testCharArray4); + } + + /** Byte arrays tests */ + @Benchmark + public boolean testByteTrue() { + return Arrays.equals(testByteArray1, testByteArray5); + } + + @Benchmark + public boolean testByteFalseEnd() { + return Arrays.equals(testByteArray1, testByteArray2); + } + + @Benchmark + public boolean testByteFalseMid() { + return Arrays.equals(testByteArray1, testByteArray3); + } + + @Benchmark + public boolean testByteFalseBeginning() { + return Arrays.equals(testByteArray1, testByteArray4); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/Dates.java b/test/micro/classes/org/openjdk/bench/java/util/Dates.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/Dates.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Dates { + + int year = 75; + int month = 11; + int day = 23; + int hours = 16; + int minutes = 47; + int seconds = 12; + + @Benchmark + public Date testEmptyConstructor() { + return new Date(); + } + + @SuppressWarnings("deprecation") + @Benchmark + public Date testIIIIIIConstructor() { + hours++; + minutes++; + seconds++; + return new Date(year, month, day, hours, minutes, seconds); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/GregorianCalendars.java b/test/micro/classes/org/openjdk/bench/java/util/GregorianCalendars.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/GregorianCalendars.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class GregorianCalendars { + + private Calendar calendar; + private long millis; + + @Setup + public void setup() { + calendar = new GregorianCalendar(); + millis = 4711L; + } + + @Benchmark + public GregorianCalendar testConstructor() { + return new GregorianCalendar(); + } + + @Benchmark + public void testUpdate() { + calendar.setTimeInMillis(millis); + millis += 1L; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/RandomNext.java b/test/micro/classes/org/openjdk/bench/java/util/RandomNext.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/RandomNext.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Tests java.util.Random's different flavours of next-methods. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class RandomNext { + + public Random rnd; + + @Setup + public void setup() { + rnd = new Random(); + } + + @Benchmark + public int testNextInt() { + return rnd.nextInt(); + } + + @Benchmark + public int testNextInt100() { + return rnd.nextInt(100); + } + + @Benchmark + public int testNextInt128() { + return rnd.nextInt(128); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/ZipFind.java b/test/micro/classes/org/openjdk/bench/java/util/ZipFind.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/ZipFind.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.concurrent.TimeUnit; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Tests ZipFile.getEntry() on the microbenchmarks.jar zip file + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ZipFind { + + // Files that exist in the microbenchmarks.jar zip file + public static final String[] existingFiles = {"org/openjdk/bench/java/util/ZipFind.class", + "org/openjdk/bench/vm/lang/Throw.class", + "org/openjdk/bench/java/nio/ByteBuffers.class"}; + public static String[] nonExistingFiles = {"/try/to/findme.not", "needle/in/a/HayStack.class"}; + + private ZipFile zip; + + @Setup + public void prepare() throws IOException, URISyntaxException { + String zipFile = this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); + zip = new ZipFile(zipFile); + + // Verify no typos in the filename lists above + assert zip.getEntry(ZipFind.nonExistingFiles[0]) == null; + assert zip.getEntry(ZipFind.existingFiles[0]) != null; + assert zip.getEntry(ZipFind.existingFiles[1]) != null; + assert zip.getEntry(ZipFind.existingFiles[2]) != null; + } + + @TearDown + public void cleanup() throws IOException { + zip.close(); + } + + @Benchmark + public ZipEntry testOneNonExisting() throws IOException { + return zip.getEntry(ZipFind.nonExistingFiles[0]); + } + + @Benchmark + public void testTwoNonExisting(Blackhole bh) throws IOException { + bh.consume(zip.getEntry(nonExistingFiles[0])); + bh.consume(zip.getEntry(nonExistingFiles[1])); + } + + @Benchmark + public void testNonExistingAndExisting(Blackhole bh) throws IOException { + bh.consume(zip.getEntry(nonExistingFiles[0])); + bh.consume(zip.getEntry(existingFiles[0])); + } + + @Benchmark + public ZipEntry testOneExisting() throws IOException { + return zip.getEntry(ZipFind.existingFiles[0]); + } + + @Benchmark + public void testTwoExisting(Blackhole bh) throws IOException { + bh.consume(zip.getEntry(existingFiles[0])); + bh.consume(zip.getEntry(existingFiles[1])); + } + + @Benchmark + public void testThreeExisting(Blackhole bh) throws IOException { + bh.consume(zip.getEntry(existingFiles[0])); + bh.consume(zip.getEntry(existingFiles[1])); + bh.consume(zip.getEntry(existingFiles[2])); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/Atomic.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Atomic.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Atomic.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class Atomic { + + public AtomicInteger aInteger; + public AtomicLong aLong; + public AtomicBoolean aBool; + + public Object testObject1; + public Object testObject2; + public AtomicReference aReference; + + /** + * The test variables are allocated every iteration so you can assume they are initialized to get similar behaviour + * across iterations + */ + @Setup(Level.Iteration) + public void setupIteration() { + testObject1 = new Object(); + testObject2 = new Object(); + aInteger = new AtomicInteger(0); + aBool = new AtomicBoolean(false); + aReference = new AtomicReference<>(testObject1); + aLong = new AtomicLong(0); + } + + + /** Always swap in value. This test should be compiled into a CAS */ + @Benchmark + @OperationsPerInvocation(2) + public void testAtomicIntegerAlways(Blackhole bh) { + bh.consume(aInteger.compareAndSet(0, 2)); + bh.consume(aInteger.compareAndSet(2, 0)); + } + + /** Never write a value just return the old one. This test should be compiled into a CAS */ + @Benchmark + public void testAtomicIntegerNever(Blackhole bh) { + bh.consume(aInteger.compareAndSet(1, 3)); + } + + /** Flips an atomic boolean on and off */ + @Benchmark + @OperationsPerInvocation(2) + public void testAtomicBooleanFlip(Blackhole bh) { + bh.consume(aBool.getAndSet(true)); + bh.consume(aBool.getAndSet(false)); + } + + /** Writes same value over and over */ + @Benchmark + public void testAtomicBooleanSame(Blackhole bh) { + bh.consume(aBool.getAndSet(true)); + } + + /** Increment and get over multiple threads */ + @Benchmark + public void testAtomicIntegerGetAndIncrement(Blackhole bh) { + bh.consume(aInteger.getAndIncrement()); + } + + /** Increment and get over multiple threads */ + @Benchmark + public void testAtomicLongGetAndIncrement(Blackhole bh) { + bh.consume(aLong.getAndIncrement()); + } + + /** Swap a few references */ + @Benchmark + @OperationsPerInvocation(2) + public void testAtomicReference(Blackhole bh) { + bh.consume(aReference.compareAndSet(testObject1, testObject2)); + bh.consume(aReference.compareAndSet(testObject2, testObject1)); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.IntUnaryOperator; + +/** + * Benchmarks assesses the performance of new Atomic* API. + * + * Implementation notes: + * - atomic instances are padded to eliminate false sharing + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class AtomicIntegerUpdateAndGet { + + private PaddedAtomicInteger count; + private int value = 42; + private IntUnaryOperator captureOp; + private IntUnaryOperator noCaptureOp; + + @Setup + public void setup() { + count = new PaddedAtomicInteger(); + noCaptureOp = new IntUnaryOperator() { + public int applyAsInt(int v) { + return v + 42; + } + }; + captureOp = new IntUnaryOperator() { + public int applyAsInt(int v) { + return v + value; + } + }; + } + + @Benchmark + public int testAddAndGet() { + return count.addAndGet(42); + } + + @Benchmark + public int testInnerNoCapture() { + return count.updateAndGet(new IntUnaryOperator() { + public int applyAsInt(int v) { + return v + 42; + } + }); + } + + @Benchmark + public int testInnerCapture() { + return count.updateAndGet(new IntUnaryOperator() { + public int applyAsInt(int v) { + return v + value; + } + }); + } + + @Benchmark + public int testInnerCaptureCached() { + return count.updateAndGet(captureOp); + } + + @Benchmark + public int testInnerNoCaptureCached() { + return count.updateAndGet(noCaptureOp); + } + + @Benchmark + public int testLambdaNoCapture() { + return count.updateAndGet(x -> x + 42); + } + + @Benchmark + public int testLambdaCapture() { + return count.updateAndGet(x -> x + value); + } + + private static class PaddedAtomicInteger extends AtomicInteger { + private volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06, pad07; + private volatile long pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses ForkJoinPool forking infrastructure. + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Benchmark) +public class ForkJoinPoolForking { + + /** + * Implementation notes: + * + * This test harnesses forking infrastructure within FJP. + * As such, no slack is given for allocating any humble number of tasks: the goal is to fork a lot. + * The approximate number of tasks is (SIZE / THRESHOLD). + * + * Raw baseline gives the idea for compute bound for this benchmark. + * FJP could be faster than baseline, because the baseline is single-threaded. + */ + + @Param("0") + private int workers; + + @Param("10000000") + private int size; + + @Param("10") + private int threshold; + + private Problem problem; + private ForkJoinPool fjpSync; + private ForkJoinPool fjpAsync; + + @Setup + public void setup() { + problem = new Problem(size); + if (workers == 0) { + workers = Runtime.getRuntime().availableProcessors(); + } + fjpSync = new ForkJoinPool(workers, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, false); + fjpAsync = new ForkJoinPool(workers, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); + } + + @TearDown + public void teardown() { + fjpSync.shutdownNow(); + fjpAsync.shutdownNow(); + } + + @Benchmark + public long baselineRaw() { + return problem.solve(); + } + + @Benchmark + public Long testExplicit_Sync() throws ExecutionException, InterruptedException { + return fjpSync.invoke(new ExplicitTask(problem, 0, problem.size(), threshold)); + } + + @Benchmark + public Long testExplicit_Async() throws ExecutionException, InterruptedException { + return fjpAsync.invoke(new ExplicitTask(problem, 0, problem.size(), threshold)); + } + + @Benchmark + public Long testStandard_Sync() throws ExecutionException, InterruptedException { + return fjpSync.invoke(new StandardTask(problem, 0, problem.size(), threshold)); + } + + @Benchmark + public Long testStandard_Async() throws ExecutionException, InterruptedException { + return fjpAsync.invoke(new StandardTask(problem, 0, problem.size(), threshold)); + } + + private static class ExplicitTask extends RecursiveTask { + private final Problem problem; + private final int l; + private final int r; + private final int thresh; + + public ExplicitTask(Problem p, int l, int r, int thresh) { + this.problem = p; + this.l = l; + this.r = r; + this.thresh = thresh; + } + + @Override + protected Long compute() { + if (r - l <= thresh) { + return problem.solve(l, r); + } + + int mid = (l + r) >>> 1; + ForkJoinTask t1 = new ExplicitTask(problem, l, mid, thresh); + ForkJoinTask t2 = new ExplicitTask(problem, mid, r, thresh); + + t1.fork(); + t2.fork(); + + long res = 0; + res += t2.join(); + res += t1.join(); + return res; + } + } + + private static class StandardTask extends RecursiveTask { + private final Problem problem; + private final int l; + private final int r; + private final int thresh; + + public StandardTask(Problem p, int l, int r, int thresh) { + this.problem = p; + this.l = l; + this.r = r; + this.thresh = thresh; + } + + @Override + protected Long compute() { + if (r - l <= thresh) { + return problem.solve(l, r); + } + + int mid = (l + r) >>> 1; + ForkJoinTask t1 = new StandardTask(problem, l, mid, thresh); + ForkJoinTask t2 = new StandardTask(problem, mid, r, thresh); + + ForkJoinTask.invokeAll(t1, t2); + long res = 0; + res += t1.join(); + res += t2.join(); + return res; + } + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses general ForkJoinPool performance with simple tasks + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class ForkJoinPoolRawCallable { + + /** + * Implementation notes: + * + * This test submits empty callables. + * Callables are submitted in batches, to prevent convoying by driver threads. + * One driver thread can saturate up to BATCH_SIZE threads. + * + * One baseline includes raw throughput, without submissions to executors. + * This is not considered as fair comparison, but left around as basic compute baseline. + * Executors could not possibly be faster than that. + * + * Another baseline includes ThreadPoolExecutor. + * Note that this baseline is inherently non-scalable with ABQ backing TPE. + * The size of ABQ is chosen to accommodate tons of threads, which can also suffer due to cache effects. + * + * Tasks are reading public volatile field to break opportunistic optimizations in loops. + * Tasks are pre-allocated to negate instantiation costs. + */ + + @Param("0") + private int workers; + + @Param("1000") + private int batchSize; + + private ThreadPoolExecutor tpe; + private ForkJoinPool fjpSync; + private ForkJoinPool fjpAsync; + private List tasks; + + public volatile int arg = 42; + + @Setup + public void setup() { + SampleTask task = new SampleTask(); + + tasks = new ArrayList<>(); + for (int c = 0; c < batchSize; c++) { + tasks.add(task); + } + + if (workers == 0) { + workers = Runtime.getRuntime().availableProcessors(); + } + + tpe = new ThreadPoolExecutor(workers, workers, 1, TimeUnit.HOURS, new ArrayBlockingQueue<>(batchSize * batchSize)); + fjpSync = new ForkJoinPool(workers, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, false); + fjpAsync = new ForkJoinPool(workers, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); + } + + @TearDown + public void teardown() { + tpe.shutdownNow(); + fjpSync.shutdownNow(); + fjpAsync.shutdownNow(); + } + + @Benchmark + public int baseline_raw() throws Exception { + int s = 0; + for (SampleTask t : tasks) { + s += t.call(); + } + return s; + } + + @Benchmark + public int baseline_TPE() throws Exception { + return doWork(tpe); + } + + @Benchmark + public int testSync() throws ExecutionException, InterruptedException { + return doWork(fjpSync); + } + + @Benchmark + public int testAsync() throws ExecutionException, InterruptedException { + return doWork(fjpAsync); + } + + public int doWork(ExecutorService service) throws ExecutionException, InterruptedException { + List> futures = new ArrayList<>(tasks.size()); + for (SampleTask task : tasks) { + futures.add(service.submit(task)); + } + + int s = 0; + for (Future future : futures) { + s += future.get(); + } + return s; + } + + public class SampleTask implements Callable { + @Override + public Integer call() throws Exception { + return arg; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses ForkJoinPool performance with dependence on threshold. + */ +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Benchmark) +public class ForkJoinPoolThresholdAutoQueued { + + /** + * Implementation notes: + * + * This test solves the problem with threshold = 1, and adaptive heuristics. The optimal level is static, + * and lies somewhere in 1..2 interval. Note the test degrades significantly when heuristic starts to fail, + * and the throughput is buried under FJP overheads. + * + * Baseline includes solving problem sequentially. Hence, each test provides the speedup for parallel execution + * versus sequential version. + */ + + @Param("0") + private int workers; + + @Param("10000000") + private int size; + + @Param({"1", "2", "3", "4", "5", "6", "7", "8"}) + private int threshold; + + private ForkJoinPool fjp; + private Problem problem; + + @Setup + public void setup() { + if (workers == 0) { + workers = Runtime.getRuntime().availableProcessors(); + } + + problem = new Problem(size); + fjp = new ForkJoinPool(workers); + } + + @TearDown + public void teardown() { + fjp.shutdownNow(); + } + + @Benchmark + public long baselineRaw() { + return problem.solve(); + } + + @Benchmark + public Long test() throws ExecutionException, InterruptedException { + return fjp.invoke(new AutoQueuedTask(threshold, problem, 0, problem.size())); + } + + private static class AutoQueuedTask extends RecursiveTask { + private final int thr; + private final Problem problem; + private final int l; + private final int r; + + public AutoQueuedTask(int thr, Problem p, int l, int r) { + this.thr = thr; + this.problem = p; + this.l = l; + this.r = r; + } + + @Override + protected Long compute() { + if (r - l <= 1 || getQueuedTaskCount() >= thr) { + return problem.solve(l, r); + } + + int mid = (l + r) >>> 1; + ForkJoinTask t1 = new AutoQueuedTask(thr, problem, l, mid); + ForkJoinTask t2 = new AutoQueuedTask(thr, problem, mid, r); + + t2.fork(); + + long res = 0; + res += t1.invoke(); + res += t2.join(); + return res; + } + } + + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses ForkJoinPool performance with dependence on threshold. + */ +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Benchmark) +public class ForkJoinPoolThresholdAutoSurplus { + + /** + * Implementation notes: + * + * This test solves the problem with threshold = 1, and adaptive heuristics. The optimal level is static, + * and lies somewhere in 1..2 interval. Note the test degrades significantly when heuristic starts to fail, + * and the throughput is buried under FJP overheads. + * + * Baseline includes solving problem sequentially. Hence, each test provides the speedup for parallel execution + * versus sequential version. + */ + + @Param("0") + private int workers; + + @Param("10000000") + private int size; + + @Param({"1", "2", "3", "4", "5", "6", "7", "8"}) + private int threshold; + + private ForkJoinPool fjp; + private Problem problem; + + @Setup + public void setup() { + if (workers == 0) { + workers = Runtime.getRuntime().availableProcessors(); + } + + problem = new Problem(size); + fjp = new ForkJoinPool(workers); + } + + @TearDown + public void teardown() { + fjp.shutdownNow(); + } + + @Benchmark + public long baselineRaw() { + return problem.solve(); + } + + @Benchmark + public Long test() throws ExecutionException, InterruptedException { + return fjp.invoke(new AutoQueuedTask(threshold, problem, 0, problem.size())); + } + + private static class AutoQueuedTask extends RecursiveTask { + private final int thr; + private final Problem problem; + private final int l; + private final int r; + + public AutoQueuedTask(int thr, Problem p, int l, int r) { + this.thr = thr; + this.problem = p; + this.l = l; + this.r = r; + } + + @Override + protected Long compute() { + if (r - l <= 1 || getSurplusQueuedTaskCount() >= thr) { + return problem.solve(l, r); + } + + int mid = (l + r) >>> 1; + ForkJoinTask t1 = new AutoQueuedTask(thr, problem, l, mid); + ForkJoinTask t2 = new AutoQueuedTask(thr, problem, mid, r); + + t2.fork(); + + long res = 0; + res += t1.invoke(); + res += t2.join(); + return res; + } + } + + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark assesses ForkJoinPool performance with dependence on threshold. + */ +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Benchmark) +public class ForkJoinPoolThresholdStatic { + + /** + * Implementation notes: + * + * This test solves the problem on different threshold levels. + * The optimal level depends on available parallelism. + * Lower thresholds will suffer because of ForkJoinPool infrastructure overheads. + * Higher thresholds will suffer because of lower available task parallelism. + * + * Baseline includes solving problem sequentially. + * Hence, each test provides the speedup for parallel execution + * versus sequential version. + */ + + @Param("0") + private int workers; + + @Param("10000000") + private int size; + + @Param({"1", "5", "10", "50", "100", "500", "1000", "5000", "10000", "50000", "100000", "500000", "1000000", "5000000", "10000000"}) + private int threshold; + + private ForkJoinPool fjp; + private Problem problem; + + @Setup + public void setup() { + if (workers == 0) { + workers = Runtime.getRuntime().availableProcessors(); + } + + problem = new Problem(size); + fjp = new ForkJoinPool(workers); + } + + @TearDown + public void teardown() { + fjp.shutdownNow(); + } + + @Benchmark + public long baselineRaw() { + return problem.solve(); + } + + @Benchmark + public Long test() throws ExecutionException, InterruptedException { + return fjp.invoke(new AdjustableThreshTask(threshold, problem, 0, problem.size())); + } + + private static class AdjustableThreshTask extends RecursiveTask { + private final int thr; + private final Problem problem; + private final int l; + private final int r; + + public AdjustableThreshTask(int thr, Problem p, int l, int r) { + this.thr = thr; + this.problem = p; + this.l = l; + this.r = r; + } + + @Override + protected Long compute() { + if (r - l <= thr) { + return problem.solve(l, r); + } + + int mid = (l + r) >>> 1; + ForkJoinTask t1 = new AdjustableThreshTask(thr, problem, l, mid); + ForkJoinTask t2 = new AdjustableThreshTask(thr, problem, mid, r); + + ForkJoinTask.invokeAll(t1, t2); + + long res = 0; + res += t1.join(); + res += t2.join(); + return res; + } + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/Locks.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Locks.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Locks.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class Locks { + + private ReentrantLock reentrantLock; + private ReentrantLock fairReentrantLock; + private ReentrantReadWriteLock reentrantRWLock; + private ReentrantReadWriteLock fairReentrantRWLock; + private Semaphore semaphore; + private Semaphore fairSemaphore; + private Lock reentrantWriteLock; + private Mutex mutex; + + @Setup + public void setup() { + reentrantLock = new ReentrantLock(false); + fairReentrantLock = new ReentrantLock(true); + reentrantRWLock = new ReentrantReadWriteLock(false); + fairReentrantRWLock = new ReentrantReadWriteLock(true); + semaphore = new Semaphore(1, false); + fairSemaphore = new Semaphore(1, true); + reentrantWriteLock = new ReentrantReadWriteLock(false).writeLock(); + mutex = new Mutex(); + } + + @Benchmark + public void testSynchronizedBlock() { + synchronized (this) { + Blackhole.consumeCPU(10); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testFairReentrantLock() { + fairReentrantLock.lock(); + try { + Blackhole.consumeCPU(10); + } finally { + fairReentrantLock.unlock(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testReentrantLock() { + reentrantLock.lock(); + try { + Blackhole.consumeCPU(10); + } finally { + reentrantLock.unlock(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testFairReentrantReadWriteLock() { + fairReentrantRWLock.readLock().lock(); + try { + Blackhole.consumeCPU(10); + } finally { + fairReentrantRWLock.readLock().unlock(); + } + fairReentrantRWLock.writeLock().lock(); + try { + Blackhole.consumeCPU(10); + } finally { + fairReentrantRWLock.writeLock().unlock(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testReentrantReadWriteLock() { + reentrantRWLock.readLock().lock(); + try { + Blackhole.consumeCPU(10); + } finally { + reentrantRWLock.readLock().unlock(); + } + reentrantRWLock.writeLock().lock(); + try { + Blackhole.consumeCPU(10); + } finally { + reentrantRWLock.writeLock().unlock(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testReentrantWriteLock() { + reentrantWriteLock.lock(); + try { + Blackhole.consumeCPU(10); + } finally { + reentrantWriteLock.unlock(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testFairSemaphore() throws InterruptedException { + fairSemaphore.acquire(); + try { + Blackhole.consumeCPU(10); + } finally { + fairSemaphore.release(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testSemaphore() throws InterruptedException { + semaphore.acquire(); + try { + Blackhole.consumeCPU(10); + } finally { + semaphore.release(); + } + Blackhole.consumeCPU(5); + } + + @Benchmark + public void testAbstractQueueSynchronizer() { + mutex.lock(); + try { + Blackhole.consumeCPU(10); + } finally { + mutex.unlock(); + } + Blackhole.consumeCPU(5); + } + + @SuppressWarnings("serial") + private final class Mutex extends AbstractQueuedSynchronizer implements Lock, java.io.Serializable { + + @Override + public boolean isHeldExclusively() { + return getState() == 1; + } + + @Override + public boolean tryAcquire(int acquires) { + return compareAndSetState(0, 1); + } + + @Override + public boolean tryRelease(int releases) { + setState(0); + return true; + } + + @Override + public Condition newCondition() { + return new ConditionObject(); + } + + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + setState(0); // reset to unlocked state + } + + @Override + public void lock() { + acquire(1); + } + + @Override + public boolean tryLock() { + return tryAcquire(1); + } + + @Override + public void lockInterruptibly() throws InterruptedException { + acquireInterruptibly(1); + } + + @Override + public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + return tryAcquireNanos(1, unit.toNanos(timeout)); + } + + @Override + public void unlock() { + release(1); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/Maps.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Maps.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Maps.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class Maps { + private SimpleRandom rng; + private Map map; + private Integer[] key; + + private int removesPerMaxRandom; + private int insertsPerMaxRandom; + private int total; + private int position; + + @Setup + public void initTest() { + int nkeys = 10000; + int pRemove = 10; + int pInsert = 90; + removesPerMaxRandom = (int) ((pRemove / 100.0 * 0x7FFFFFFFL)); + insertsPerMaxRandom = (int) ((pInsert / 100.0 * 0x7FFFFFFFL)); + + rng = new SimpleRandom(); + map = new ConcurrentHashMap<>(); + total = 0; + key = new Integer[nkeys]; + for (int i = 0; i < key.length; ++i) { + key[i] = new Integer(rng.next()); + } + position = key.length / 2; + } + + @Benchmark + @Threads(4) + public void testConcurrentHashMap() { + int pos = position; + // random-walk around key positions, bunching accesses + int r = rng.next(); + pos += (r & 7) - 3; + while (pos >= key.length) { + pos -= key.length; + } + while (pos < 0) { + pos += key.length; + } + Integer k = key[pos]; + Integer x = map.get(k); + if (x != null) { + if (x.intValue() != k.intValue()) { + throw new Error("bad mapping: " + x + " to " + k); + } + + if (r < removesPerMaxRandom) { + if (map.remove(k) != null) { + pos = total % key.length; // move from position + } + } + } else if (r < insertsPerMaxRandom) { + ++pos; + map.put(k, k); + } + total += r; + position = pos; + } + + private static class SimpleRandom { + private final static long multiplier = 0x5DEECE66DL; + private final static long addend = 0xBL; + private final static long mask = (1L << 48) - 1; + private final static AtomicLong seq = new AtomicLong(1); + private long seed = System.nanoTime() + seq.getAndIncrement(); + + public int next() { + long nextSeed = (seed * multiplier + addend) & mask; + seed = nextSeed; + return ((int) (nextSeed >>> 17)) & 0x7FFFFFFF; + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/Problem.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Problem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Problem.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + + +/** + * Generic problem for concurrency tests. + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +public class Problem { + + /* + * Implementation notes: + * + * This problem makes its bidding to confuse loop unrolling and CSE, and as such break loop optimizations. + * Should loop optimizations be allowed, the performance with different (l, r) could change non-linearly. + */ + + private final int[] data; + private final int size; + + public Problem(int size) { + this.size = size; + data = new int[size]; + } + + public long solve() { + return solve(0, size); + } + + public long solve(int l, int r) { + long sum = 0; + for (int c = l; c < r; c++) { + int v = hash(data[c]); + if (filter(v)) { + sum += v; + } + } + return sum; + } + + public int size() { + return size; + } + + public static int hash(int x) { + x ^= (x << 21); + x ^= (x >>> 31); + x ^= (x << 4); + return x; + } + + public static boolean filter(int i) { + return ((i & 0b101) == 0); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * Tests the different blocking queues in the java.util.concurrent package. + * The tests are done with a single producer and a variable number of consumers. + * The tests are created from Doug Lea's concurrent test suite. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class ProducerConsumer { + + @Param("100") + private int capacity; + + @Param + private QueueType type; + + private BlockingQueue q; + private Producer prod; + + @Setup + public void prepare() { + switch (type) { + case ABQ_F: + q = new ArrayBlockingQueue<>(capacity, true); + break; + case ABQ_NF: + q = new ArrayBlockingQueue<>(capacity, false); + break; + case LBQ: + q = new LinkedBlockingQueue<>(capacity); + break; + case PBQ: + q = new PriorityBlockingQueue<>(capacity); + break; + default: + throw new RuntimeException(); + } + + prod = new Producer(q); + prod.start(); + } + + @TearDown + public void teardown() { + prod.halt(); + } + + @Benchmark + public void test() { + try { + int last = -1; + int v = q.take(); + if (v < last) { + throw new Error("Out-of-Order transfer"); + } + Blackhole.consumeCPU(10); + } catch (Exception ie) { + } + } + + public enum QueueType { + LBQ, + ABQ_NF, + ABQ_F, + PBQ, + } + + private class Producer extends Thread { + private final BlockingQueue queue; + private int i = 0; + private volatile boolean running; + + public Producer(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + running = true; + try { + while (running) { + queue.put(i++); + } + } catch (Exception ie) { + } + } + + public void halt() { + running = false; + this.interrupt(); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/Queues.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Queues.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/Queues.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class Queues { + + @Param("100") + private int capacity; + + @Param + private QueueType type; + + public enum QueueType { + LBQ, + ABQ_NF, + ABQ_F, + PBQ, + } + + private BlockingQueue q; + + @Setup + public void setup() { + switch (type) { + case ABQ_F: + q = new ArrayBlockingQueue<>(capacity, true); + break; + case ABQ_NF: + q = new ArrayBlockingQueue<>(capacity, false); + break; + case LBQ: + q = new LinkedBlockingQueue<>(capacity); + break; + case PBQ: + q = new PriorityBlockingQueue<>(capacity); + break; + default: + throw new RuntimeException(); + } + } + + @Benchmark + public void test() { + try { + int l = (int) System.nanoTime(); + Integer item = q.poll(); + if (item != null) { + Blackhole.consumeCPU(5); + } else { + Blackhole.consumeCPU(10); + while (!q.offer(l)) { + Blackhole.consumeCPU(5); + } + } + } catch (Exception ie) { + throw new Error("iteration failed"); + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import org.openjdk.jmh.annotations.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ThreadLocalRandomNextInt { + + @State(Scope.Benchmark) + public static class Global { + public ThreadLocal tlr; + private List> contaminators; // reachable, non-garbage-collectable + + @Setup(Level.Trial) + public void setup() { + tlr = new ThreadLocal() { + @Override + protected Random initialValue() { + return java.util.concurrent.ThreadLocalRandom.current(); + } + }; + + // contaminate ThreadLocals + int contaminatorCount = Integer.getInteger("contaminators", 0); + contaminators = new ArrayList<>(contaminatorCount); + for (int i = 0; i < contaminatorCount; i++) { + final int finalI = i; + ThreadLocal tl = new ThreadLocal() { + @Override + protected Integer initialValue() { + return finalI; + } + }; + contaminators.add(tl); + tl.get(); + } + } + } + + @State(Scope.Thread) + public static class Local { + public java.util.concurrent.ThreadLocalRandom tlr; + + @Setup(Level.Trial) + public void setup() { + tlr = java.util.concurrent.ThreadLocalRandom.current(); + } + } + + @Benchmark + public int baseline(Local l) { + return l.tlr.nextInt(); + } + + @Benchmark + public int testJUC() { + return java.util.concurrent.ThreadLocalRandom.current().nextInt(); + } + + @Benchmark + public int testLang(Global g) { + return g.tlr.get().nextInt(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/logging/LogRecord.java b/test/micro/classes/org/openjdk/bench/java/util/logging/LogRecord.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/logging/LogRecord.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.logging; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class LogRecord { + private Logger logger; + + @Setup + public void setup(final Blackhole bh) { + try { + logger = Logger.getLogger("logger"); + logger.addHandler(new Handler() { + @Override + public void publish(java.util.logging.LogRecord record) { + bh.consume(record); + } + + @Override + public void flush() { + // do nothing + } + + @Override + public void close() throws SecurityException { + // do nothing + } + }); + logger.setLevel(Level.FINE); + logger.setUseParentHandlers(false); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @Benchmark + public void testFine() { + logger.log(Level.FINE, "test message"); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/AllMatcher.java b/test/micro/classes/org/openjdk/bench/java/util/stream/AllMatcher.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/AllMatcher.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for checking different "allMatch" schemes. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AllMatcher { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - all operations have similar semantics + * - these use the qualifier duality: all(P(x)) === !(exists(!P(x)) + */ + + @Param("100000") + private int size; + + private LongPredicate op; + + @Setup + public void setup() { + op = new LongPredicate() { + @Override + public boolean test(long x) { + return true; + } + }; + } + + @Benchmark + public boolean seq_anyMatch() { + return LongStream.range(0, size).allMatch(op); + } + + @Benchmark + public boolean seq_filter_findFirst() { + return !(LongStream.range(0, size).filter(op.negate()).findFirst().isPresent()); + } + + @Benchmark + public boolean seq_filter_findAny() { + return !(LongStream.range(0, size).filter(op.negate()).findAny().isPresent()); + } + + @Benchmark + public boolean par_anyMatch() { + return LongStream.range(0, size).parallel().allMatch(op); + } + + @Benchmark + public boolean par_filter_findFirst() { + return !(LongStream.range(0, size).parallel().filter(op.negate()).findFirst().isPresent()); + } + + @Benchmark + public boolean par_filter_findAny() { + return !(LongStream.range(0, size).parallel().filter(op.negate()).findAny().isPresent()); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/AnyMatcher.java b/test/micro/classes/org/openjdk/bench/java/util/stream/AnyMatcher.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/AnyMatcher.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for checking different "anyMatch" schemes. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AnyMatcher { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - all operations have similar semantics + */ + + @Param("100000") + private int size; + + private LongPredicate op; + + @Setup + public void setup() { + op = new LongPredicate() { + @Override + public boolean test(long x) { + return false; + } + }; + } + + @Benchmark + public boolean seq_anyMatch() { + return LongStream.range(0, size).anyMatch(op); + } + + @Benchmark + public boolean seq_filter_findFirst() { + return LongStream.range(0, size).filter(op).findFirst().isPresent(); + } + + @Benchmark + public boolean seq_filter_findAny() { + return LongStream.range(0, size).filter(op).findAny().isPresent(); + } + + @Benchmark + public boolean par_anyMatch() { + return LongStream.range(0, size).parallel().anyMatch(op); + } + + @Benchmark + public boolean par_filter_findFirst() { + return LongStream.range(0, size).parallel().filter(op).findFirst().isPresent(); + } + + @Benchmark + public boolean par_filter_findAny() { + return LongStream.range(0, size).parallel().filter(op).findAny().isPresent(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/Decomposition.java b/test/micro/classes/org/openjdk/bench/java/util/stream/Decomposition.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/Decomposition.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * This benchmark is the golden benchmark for decompositions. + * There are at least four parameters to juggle: + * - pool parallelism (P), controlled via -Djava.util.concurrent.ForkJoinUtils.pool.parallelism + * - problem size (N), controlled as benchmark param + * - operation cost (Q), controlled as benchmark param + * - number of clients (C), controlled via -t option in harness + * + * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) + */ +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +public class Decomposition { + + @Param("1000") + private int N; + + @Param("1000") + private int Q; + + @State(Scope.Thread) + public static class Thinktime { + @Param("10") + private int S; + + @Setup(Level.Invocation) + public void sleep() throws InterruptedException { + TimeUnit.MILLISECONDS.sleep(S); + } + } + + @Benchmark + public long saturated_sequential() throws InterruptedException { + return LongStream.range(1, N).filter(k -> doWork(k, Q)).sum(); + } + + @Benchmark + public long thinktime_sequential(Thinktime t) throws InterruptedException { + return LongStream.range(1, N).filter(k -> doWork(k, Q)).sum(); + } + + @Benchmark + public long saturated_parallel() throws InterruptedException { + return LongStream.range(1, N).parallel().filter(k -> doWork(k, Q)).sum(); + } + + @Benchmark + public long thinktime_parallel(Thinktime t) throws InterruptedException { + return LongStream.range(1, N).parallel().filter(k -> doWork(k, Q)).sum(); + } + + /** + * Make some work. + * This method have a couple of distinguishable properties: + * - the run time is linear with Q + * - the computation is dependent on input, preventing common reductions + * - the returned result is dependent on loop result, preventing dead code elimination + * - the returned result is almost always false + * + * This code uses inlined version of ThreadLocalRandom.next() to mitigate the edge effects + * of acquiring TLR every single call. + * + * @param input input + * @return result + */ + public static boolean doWork(long input, long count) { + long t = input; + for (int i = 0; i < count; i++) { + t += (t * 0x5DEECE66DL + 0xBL) & (0xFFFFFFFFFFFFL); + } + return (t == 0); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/NoneMatcher.java b/test/micro/classes/org/openjdk/bench/java/util/stream/NoneMatcher.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/NoneMatcher.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for checking different "noneMatch" schemes. + * + * @author Aleksey Shipilev, aleksey.shipilev@oracle.com + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class NoneMatcher { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - all operations have similar semantics + * - these use the qualifier duality: + * exists(P(x)) === !all(!P(x)) => + * !exists(P(x)) === all(!P(x)) + */ + + @Param("100000") + private int size; + + private LongPredicate op; + + @Setup + public void setup() { + op = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + } + + @Benchmark + public boolean seq_anyMatch() { + return LongStream.range(0, size).noneMatch(op); + } + + @Benchmark + public boolean par_anyMatch() { + return LongStream.range(0, size).parallel().noneMatch(op); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/Reducers.java b/test/micro/classes/org/openjdk/bench/java/util/stream/Reducers.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/Reducers.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongBinaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for checking different reduce schemes. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Reducers { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private LongBinaryOperator op; + + @Setup + public void setup() { + op = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + } + + @Benchmark + public long seq_reduce() { + return LongStream.range(0, size).reduce(op).getAsLong(); + } + + @Benchmark + public long par_reduce() { + return LongStream.range(0, size).parallel().reduce(op).getAsLong(); + } + + @Benchmark + public long seq_reduce_base() { + return LongStream.range(0, size).reduce(0L, op); + } + + @Benchmark + public long par_reduce_base() { + return LongStream.range(0, size).parallel().reduce(0L, op); + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops; + +public class LongAccumulator { + + long acc; + + public LongAccumulator() { + acc = 0; + } + + public void add(long v) { + acc += v; + } + + public void merge(LongAccumulator other) { + acc += other.acc; + } + + public long get() { + return acc; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for allMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AllMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always true to avert shortcurcuiting + */ + + @Param("100000") + private int size; + + private Predicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new Predicate() { + @Override + public boolean test(Long v) { + return true; + } + }; + p2 = new Predicate() { + @Override + public boolean test(Long v) { + return true; + } + }; + p3 = new Predicate() { + @Override + public boolean test(Long v) { + return true; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).boxed().allMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().allMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().allMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().allMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().boxed().allMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().allMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for allMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AllMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become false closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private Predicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new Predicate() { + @Override + public boolean test(Long v) { + return v < offset; + } + }; + pMid = new Predicate() { + @Override + public boolean test(Long v) { + return v < size / 2; + } + }; + pEnd = new Predicate() { + @Override + public boolean test(Long v) { + return v < size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).boxed().allMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).boxed().allMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).boxed().allMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().boxed().allMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().boxed().allMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().boxed().allMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for anyMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AnyMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always false to avert shortcurcuiting + */ + + @Param("100000") + private int size; + + private Predicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + p2 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + p3 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).boxed().anyMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().anyMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().anyMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().anyMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().boxed().anyMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().anyMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for anyMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AnyMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become true closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private Predicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new Predicate() { + @Override + public boolean test(Long v) { + return v > offset; + } + }; + pMid = new Predicate() { + @Override + public boolean test(Long v) { + return v > size / 2; + } + }; + pEnd = new Predicate() { + @Override + public boolean test(Long v) { + return v > size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).boxed().anyMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).boxed().anyMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).boxed().anyMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().boxed().anyMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().boxed().anyMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().boxed().anyMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Filter.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Filter.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Filter.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for filter() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Filter { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive predicates is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private Predicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new Predicate() { + @Override + public boolean test(Long l) { + return (l & 0b11111111) == 0; + } + }; + p2 = new Predicate() { + @Override + public boolean test(Long l) { + return (l & 0b00001111) == 0; + } + }; + p3 = new Predicate() { + @Override + public boolean test(Long l) { + return (l & 0x00000011) == 0; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .boxed() + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .boxed() + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_111() { + return LongStream.range(0, size) + .boxed() + .filter(p1) + .filter(p1) + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_111() { + return LongStream.range(0, size).parallel() + .boxed() + .filter(p1) + .filter(p1) + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_123() { + return LongStream.range(0, size) + .boxed() + .filter(p1) + .filter(p2) + .filter(p3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_123() { + return LongStream.range(0, size).parallel() + .boxed() + .filter(p1) + .filter(p2) + .filter(p3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for findAny() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class FindAny { + + @Param("100000") + private int size; + + @Benchmark + public Long seq_invoke() { + return LongStream.range(0, size).boxed().findAny().get(); + } + + @Benchmark + public Long par_invoke() { + return LongStream.range(0, size).parallel().boxed().findAny().get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for findFirst() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class FindFirst { + + @Param("100000") + private int size; + + @Benchmark + public Long seq_invoke() { + return LongStream.range(0, size).boxed().findFirst().get(); + } + + @Benchmark + public Long par_invoke() { + return LongStream.range(0, size).parallel().boxed().findFirst().get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.Consumer; +import java.util.stream.LongStream; + +/** + * Benchmark for forEach() operations. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class ForEach { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + */ + + @Param("100000") + private int size; + + private LongAdder sink; + private Consumer b1, b2, b3; + + @Setup + public void setup() { + sink = new LongAdder(); + b1 = new Consumer() { + @Override + public void accept(Long v) { + sink.add(v); + } + }; + b2 = new Consumer() { + @Override + public void accept(Long v) { + sink.add(v); + } + }; + b3 = new Consumer() { + @Override + public void accept(Long v) { + sink.add(v); + } + }; + } + + @Benchmark + public long seq_invoke() { + LongStream.range(0, size).boxed().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long seq_chain111() { + LongStream.range(0, size).boxed().forEach(b1); + LongStream.range(0, size).boxed().forEach(b1); + LongStream.range(0, size).boxed().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long seq_chain123() { + LongStream.range(0, size).boxed().forEach(b1); + LongStream.range(0, size).boxed().forEach(b2); + LongStream.range(0, size).boxed().forEach(b3); + return sink.sum(); + } + + @Benchmark + public long par_invoke() { + LongStream.range(0, size).parallel().boxed().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long par_chain111() { + LongStream.range(0, size).parallel().boxed().forEach(b1); + LongStream.range(0, size).parallel().boxed().forEach(b1); + LongStream.range(0, size).parallel().boxed().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long par_chain123() { + LongStream.range(0, size).parallel().boxed().forEach(b1); + LongStream.range(0, size).parallel().boxed().forEach(b2); + LongStream.range(0, size).parallel().boxed().forEach(b3); + return sink.sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Limit.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Limit.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Limit.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for limit() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Limit { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the tests include: + * - return nothing + * - return just a single element + * - return half + * - return all but last element + * - return all + */ + + @Param("100000") + private int size; + + @Benchmark + public long seq_baseline() { + return LongStream.range(0, size) + .boxed() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limit0() { + return LongStream.range(0, size) + .boxed() + .limit(0) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limit1() { + return LongStream.range(0, size) + .boxed() + .limit(1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitHalf() { + return LongStream.range(0, size) + .boxed() + .limit(size / 2) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitFull() { + return LongStream.range(0, size) + .boxed() + .limit(size - 1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitFullest() { + return LongStream.range(0, size) + .boxed() + .limit(size) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_baseline() { + return LongStream.range(0, size).parallel() + .boxed() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limit0() { + return LongStream.range(0, size).parallel() + .boxed() + .limit(0) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limit1() { + return LongStream.range(0, size).parallel() + .boxed() + .limit(1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitHalf() { + return LongStream.range(0, size).parallel() + .boxed() + .limit(size / 2) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitFull() { + return LongStream.range(0, size).parallel() + .boxed().limit(size - 1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitFullest() { + return LongStream.range(0, size).parallel() + .boxed() + .limit(size) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Map.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Map.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Map.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.LongStream; + +/** + * Benchmark for map() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Map { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private Function m1, m2, m3; + + @Setup + public void setup() { + m1 = new Function() { + @Override + public Long apply(Long l) { + return l * 2; + } + }; + m2 = new Function() { + @Override + public Long apply(Long l) { + return l * 2; + } + }; + m3 = new Function() { + @Override + public Long apply(Long l) { + return l * 2; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .boxed() + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .boxed() + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_111() { + return LongStream.range(0, size) + .boxed() + .map(m1) + .map(m1) + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_111() { + return LongStream.range(0, size).parallel() + .boxed() + .map(m1) + .map(m1) + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_123() { + return LongStream.range(0, size) + .boxed() + .map(m1) + .map(m2) + .map(m3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_123() { + return LongStream.range(0, size).parallel() + .boxed() + .map(m1) + .map(m2) + .map(m3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for noneMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class NoneMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always false to avert shortcurcuiting + */ + + @Param("100000") + private int size; + + private Predicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + p2 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + p3 = new Predicate() { + @Override + public boolean test(Long v) { + return false; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).boxed().noneMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().noneMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().noneMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).boxed().noneMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().boxed().noneMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().boxed().noneMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +/** + * Benchmark for noneMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class NoneMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become true closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private Predicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new Predicate() { + @Override + public boolean test(Long v) { + return v > offset; + } + }; + pMid = new Predicate() { + @Override + public boolean test(Long v) { + return v > size / 2; + } + }; + pEnd = new Predicate() { + @Override + public boolean test(Long v) { + return v > size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).boxed().noneMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).boxed().noneMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).boxed().noneMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().boxed().noneMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().boxed().noneMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().boxed().noneMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for reduce() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Reduce { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + */ + + @Param("100000") + private int size; + + private BinaryOperator op1, op2, op3; + + @Setup + public void setup() { + op1 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + op2 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + op3 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).boxed().reduce(op1).get(); + } + + @Benchmark + public long seq_chain_111() { + long l = 0; + l += LongStream.range(0, size).boxed().reduce(op1).get(); + l += LongStream.range(0, size).boxed().reduce(op1).get(); + l += LongStream.range(0, size).boxed().reduce(op1).get(); + return l; + } + + @Benchmark + public long seq_chain_123() { + long l = 0; + l += LongStream.range(0, size).boxed().reduce(op1).get(); + l += LongStream.range(0, size).boxed().reduce(op2).get(); + l += LongStream.range(0, size).boxed().reduce(op3).get(); + return l; + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().boxed().reduce(op1).get(); + } + + @Benchmark + public long par_chain_111() { + long l = 0; + l += LongStream.range(0, size).parallel().boxed().reduce(op1).get(); + l += LongStream.range(0, size).parallel().boxed().reduce(op1).get(); + l += LongStream.range(0, size).parallel().boxed().reduce(op1).get(); + return l; + } + + @Benchmark + public long par_chain_123() { + long l = 0; + l += LongStream.range(0, size).parallel().boxed().reduce(op1).get(); + l += LongStream.range(0, size).parallel().boxed().reduce(op2).get(); + l += LongStream.range(0, size).parallel().boxed().reduce(op3).get(); + return l; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for reduce()-base operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class ReduceBase { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private BinaryOperator op1, op2, op3; + + @Setup + public void setup() { + op1 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + op2 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + op3 = new BinaryOperator() { + @Override + public Long apply(Long l, Long r) { + return (l > r) ? l : r; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).boxed().reduce(0L, op1); + } + + @Benchmark + public long seq_chain_111() { + long l = 0; + l += LongStream.range(0, size).boxed().reduce(0L, op1); + l += LongStream.range(0, size).boxed().reduce(0L, op1); + l += LongStream.range(0, size).boxed().reduce(0L, op1); + return l; + } + + @Benchmark + public long seq_chain_123() { + long l = 0; + l += LongStream.range(0, size).boxed().reduce(0L, op1); + l += LongStream.range(0, size).boxed().reduce(0L, op2); + l += LongStream.range(0, size).boxed().reduce(0L, op3); + return l; + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().boxed().reduce(0L, op1); + } + + @Benchmark + public long par_chain_111() { + long l = 0; + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op1); + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op1); + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op1); + return l; + } + + @Benchmark + public long par_chain_123() { + long l = 0; + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op1); + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op2); + l += LongStream.range(0, size).parallel().boxed().reduce(0L, op3); + return l; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Comparator; +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for sorted() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Sorted { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - consecutive sorts should reuse the knowledge that stream was sorted already + */ + + @Param("100000") + private int size; + + private Comparator cmp; + + @Setup + public void setup() { + cmp = new Comparator() { + @Override + public int compare(Long x, Long y) { + return (x > y) ? 1 : (x < y ? -1 : 0); + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .boxed() + .sorted(cmp) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .boxed() + .sorted(cmp) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain() { + return LongStream.range(0, size) + .boxed() + .sorted(cmp) + .sorted(cmp) + .sorted(cmp) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain() { + return LongStream.range(0, size).parallel() + .boxed() + .sorted(cmp) + .sorted(cmp) + .sorted(cmp) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for both sorted() and uniq() operations. + * Sorts long range modulo power of two, then does unique elements. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class SortedUnique { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + */ + + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .boxed() + .mapToLong((l) -> l & 0xFFFF) + .sorted() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .boxed() + .mapToLong((l) -> l & 0xFFFF) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.ref; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for uniqueElements() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class UniqueElements { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .boxed() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .boxed() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain() { + return LongStream.range(0, size) + .boxed() + .distinct() + .distinct() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain() { + return LongStream.range(0, size).parallel() + .boxed() + .distinct() + .distinct() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for allMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AllMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always true to avert shortcurcuiting + */ + + @Param("100000") + private int size; + + private LongPredicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new LongPredicate() { + @Override + public boolean test(long v) { + return true; + } + }; + p2 = new LongPredicate() { + @Override + public boolean test(long v) { + return true; + } + }; + p3 = new LongPredicate() { + @Override + public boolean test(long v) { + return true; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).allMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).allMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).allMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).allMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().allMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().allMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().allMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().allMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().allMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for allMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AllMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become false closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private LongPredicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new LongPredicate() { + @Override + public boolean test(long v) { + return v < offset; + } + }; + pMid = new LongPredicate() { + @Override + public boolean test(long v) { + return v < size / 2; + } + }; + pEnd = new LongPredicate() { + @Override + public boolean test(long v) { + return v < size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).allMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).allMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).allMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().allMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().allMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().allMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for anyMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AnyMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always false to avert shortcurcuiting + */ + @Param("100000") + private int size; + + private LongPredicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + p2 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + p3 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).anyMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).anyMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).anyMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).anyMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().anyMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().anyMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().anyMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().anyMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().anyMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for anyMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AnyMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become true closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private LongPredicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new LongPredicate() { + @Override + public boolean test(long v) { + return v > offset; + } + }; + pMid = new LongPredicate() { + @Override + public boolean test(long v) { + return v > size / 2; + } + }; + pEnd = new LongPredicate() { + @Override + public boolean test(long v) { + return v > size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).anyMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).anyMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).anyMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().anyMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().anyMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().anyMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Filter.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Filter.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Filter.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for filter() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Filter { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive predicates is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private LongPredicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new LongPredicate() { + @Override + public boolean test(long l) { + return (l & 0b11111111) == 0; + } + }; + p2 = new LongPredicate() { + @Override + public boolean test(long l) { + return (l & 0b00001111) == 0; + } + }; + p3 = new LongPredicate() { + @Override + public boolean test(long l) { + return (l & 0x00000011) == 0; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_111() { + return LongStream.range(0, size) + .filter(p1) + .filter(p1) + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_111() { + return LongStream.range(0, size).parallel() + .filter(p1) + .filter(p1) + .filter(p1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_123() { + return LongStream.range(0, size) + .filter(p1) + .filter(p2) + .filter(p3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_123() { + return LongStream.range(0, size).parallel() + .filter(p1) + .filter(p2) + .filter(p3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindAny.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindAny.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindAny.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for findAny() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class FindAny { + + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).findAny().getAsLong(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().findAny().getAsLong(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for findFirst() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class FindFirst { + + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).findFirst().getAsLong(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().findFirst().getAsLong(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ForEach.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ForEach.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ForEach.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.LongConsumer; +import java.util.stream.LongStream; + +/** + * Benchmark for forEach() operations. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class ForEach { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + */ + @Param("100000") + private int size; + + private LongConsumer b1, b2, b3; + private LongAdder sink; + + @Setup + public void setup() { + sink = new LongAdder(); + b1 = new LongConsumer() { + @Override + public void accept(long v) { + sink.add(v); + } + }; + b2 = new LongConsumer() { + @Override + public void accept(long v) { + sink.add(v); + } + }; + b3 = new LongConsumer() { + @Override + public void accept(long v) { + sink.add(v); + } + }; + } + + @Benchmark + public long seq_invoke() { + LongStream.range(0, size).forEach(b1); + return sink.sum(); + } + + @Benchmark + public long seq_chain111() { + LongStream.range(0, size).forEach(b1); + LongStream.range(0, size).forEach(b1); + LongStream.range(0, size).forEach(b1); + return sink.sum(); + } + + @Benchmark + public long seq_chain123() { + LongStream.range(0, size).forEach(b1); + LongStream.range(0, size).forEach(b2); + LongStream.range(0, size).forEach(b3); + return sink.sum(); + } + + @Benchmark + public long par_invoke() { + LongStream.range(0, size).parallel().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long par_chain111() { + LongStream.range(0, size).parallel().forEach(b1); + LongStream.range(0, size).parallel().forEach(b1); + LongStream.range(0, size).parallel().forEach(b1); + return sink.sum(); + } + + @Benchmark + public long par_chain123() { + LongStream.range(0, size).parallel().forEach(b1); + LongStream.range(0, size).parallel().forEach(b2); + LongStream.range(0, size).parallel().forEach(b3); + return sink.sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Limit.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Limit.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Limit.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for limit() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Limit { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the tests include: + * - return nothing + * - return just a single element + * - return half + * - return all but last element + * - return all + */ + + @Param("100000") + private int size; + + @Benchmark + public long seq_baseline() { + return LongStream.range(0, size) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limit0() { + return LongStream.range(0, size) + .limit(0) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limit1() { + return LongStream.range(0, size) + .limit(1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitHalf() { + return LongStream.range(0, size) + .limit(size / 2) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitFull() { + return LongStream.range(0, size) + .limit(size - 1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_limitFullest() { + return LongStream.range(0, size) + .limit(size) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_baseline() { + return LongStream.range(0, size).parallel() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limit0() { + return LongStream.range(0, size).parallel() + .limit(0) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limit1() { + return LongStream.range(0, size).parallel() + .limit(1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitHalf() { + return LongStream.range(0, size).parallel() + .limit(size / 2) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitFull() { + return LongStream.range(0, size).parallel() + .limit(size - 1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_limitFullest() { + return LongStream.range(0, size).parallel() + .limit(size) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Map.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Map.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Map.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongUnaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for map() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Map { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + + @Param("100000") + private int size; + + private LongUnaryOperator m1, m2, m3; + + @Setup + public void setup() { + m1 = new LongUnaryOperator() { + @Override + public long applyAsLong(long l) { + return l * 2; + } + }; + m2 = new LongUnaryOperator() { + @Override + public long applyAsLong(long l) { + return l * 2; + } + }; + m3 = new LongUnaryOperator() { + @Override + public long applyAsLong(long l) { + return l * 2; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_111() { + return LongStream.range(0, size) + .map(m1) + .map(m1) + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_111() { + return LongStream.range(0, size).parallel() + .map(m1) + .map(m1) + .map(m1) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain_123() { + return LongStream.range(0, size) + .map(m1) + .map(m2) + .map(m3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain_123() { + return LongStream.range(0, size).parallel() + .map(m1) + .map(m2) + .map(m3) + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for noneMatch() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class NoneMatch { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the predicates are always false to avert shortcurcuiting + */ + + @Param("100000") + private int size; + + private LongPredicate p1, p2, p3; + + @Setup + public void setup() { + p1 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + p2 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + p3 = new LongPredicate() { + @Override + public boolean test(long v) { + return false; + } + }; + } + + @Benchmark + public boolean seq_invoke() { + return LongStream.range(0, size).noneMatch(p1); + } + + @Benchmark + public int seq_chain111() { + int s = 0; + s += (LongStream.range(0, size).noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).noneMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int seq_chain123() { + int s = 0; + s += (LongStream.range(0, size).noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).noneMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).noneMatch(p3)) ? 1 : 0; + return s; + } + + @Benchmark + public boolean par_invoke() { + return LongStream.range(0, size).parallel().noneMatch(p1); + } + + @Benchmark + public int par_chain111() { + int s = 0; + s += (LongStream.range(0, size).parallel().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().noneMatch(p1)) ? 1 : 0; + return s; + } + + @Benchmark + public int par_chain123() { + int s = 0; + s += (LongStream.range(0, size).parallel().noneMatch(p1)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().noneMatch(p2)) ? 1 : 0; + s += (LongStream.range(0, size).parallel().noneMatch(p3)) ? 1 : 0; + return s; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark for noneMatch() operation. + * Focuses on short-circuiting behavior. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class NoneMatchShort { + + /** + * Implementation notes: + * - operations are explicit inner classes to untangle unwanted lambda effects + * - test the predicate which will become true closer to start, in the middle, and closer to the end + */ + + @Param("100000") + private int size; + + @Param("100") + private int offset; + + private LongPredicate pMid, pStart, pEnd; + + @Setup + public void setup() { + pStart = new LongPredicate() { + @Override + public boolean test(long v) { + return v > offset; + } + }; + pMid = new LongPredicate() { + @Override + public boolean test(long v) { + return v > size / 2; + } + }; + pEnd = new LongPredicate() { + @Override + public boolean test(long v) { + return v > size - offset; + } + }; + } + + @Benchmark + public boolean seq_start() { + return LongStream.range(0, size).noneMatch(pStart); + } + + @Benchmark + public boolean seq_mid() { + return LongStream.range(0, size).noneMatch(pMid); + } + + @Benchmark + public boolean seq_end() { + return LongStream.range(0, size).noneMatch(pEnd); + } + + @Benchmark + public boolean par_start() { + return LongStream.range(0, size).parallel().noneMatch(pStart); + } + + @Benchmark + public boolean par_mid() { + return LongStream.range(0, size).parallel().noneMatch(pMid); + } + + @Benchmark + public boolean par_end() { + return LongStream.range(0, size).parallel().noneMatch(pEnd); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Reduce.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Reduce.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Reduce.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongBinaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for reduce() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Reduce { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + */ + @Param("100000") + private int size; + + private LongBinaryOperator op1, op2, op3; + + @Setup + public void setup() { + op1 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + op2 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + op3 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).reduce(op1).getAsLong(); + } + + @Benchmark + public long seq_chain_111() { + long l = 0; + l += LongStream.range(0, size).reduce(op1).getAsLong(); + l += LongStream.range(0, size).reduce(op1).getAsLong(); + l += LongStream.range(0, size).reduce(op1).getAsLong(); + return l; + } + + @Benchmark + public long seq_chain_123() { + long l = 0; + l += LongStream.range(0, size).reduce(op1).getAsLong(); + l += LongStream.range(0, size).reduce(op2).getAsLong(); + l += LongStream.range(0, size).reduce(op3).getAsLong(); + return l; + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().reduce(op1).getAsLong(); + } + + @Benchmark + public long par_chain_111() { + long l = 0; + l += LongStream.range(0, size).parallel().reduce(op1).getAsLong(); + l += LongStream.range(0, size).parallel().reduce(op1).getAsLong(); + l += LongStream.range(0, size).parallel().reduce(op1).getAsLong(); + return l; + } + + @Benchmark + public long par_chain_123() { + long l = 0; + l += LongStream.range(0, size).parallel().reduce(op1).getAsLong(); + l += LongStream.range(0, size).parallel().reduce(op2).getAsLong(); + l += LongStream.range(0, size).parallel().reduce(op3).getAsLong(); + return l; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.function.LongBinaryOperator; +import java.util.stream.LongStream; + +/** + * Benchmark for reduce()-base operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class ReduceBase { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + @Param("100000") + private int size; + + private LongBinaryOperator op1, op2, op3; + + @Setup + public void setup() { + op1 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + op2 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + op3 = new LongBinaryOperator() { + @Override + public long applyAsLong(long l, long r) { + return (l > r) ? l : r; + } + }; + } + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size).reduce(0L, op1); + } + + @Benchmark + public long seq_chain_111() { + long l = 0; + l += LongStream.range(0, size).reduce(0L, op1); + l += LongStream.range(0, size).reduce(0L, op1); + l += LongStream.range(0, size).reduce(0L, op1); + return l; + } + + @Benchmark + public long seq_chain_123() { + long l = 0; + l += LongStream.range(0, size).reduce(0L, op1); + l += LongStream.range(0, size).reduce(0L, op2); + l += LongStream.range(0, size).reduce(0L, op3); + return l; + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel().reduce(0L, op1); + } + + @Benchmark + public long par_chain_111() { + long l = 0; + l += LongStream.range(0, size).parallel().reduce(0L, op1); + l += LongStream.range(0, size).parallel().reduce(0L, op1); + l += LongStream.range(0, size).parallel().reduce(0L, op1); + return l; + } + + @Benchmark + public long par_chain_123() { + long l = 0; + l += LongStream.range(0, size).parallel().reduce(0L, op1); + l += LongStream.range(0, size).parallel().reduce(0L, op2); + l += LongStream.range(0, size).parallel().reduce(0L, op3); + return l; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Sorted.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Sorted.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/Sorted.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for sorted() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Sorted { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - consecutive sorts should reuse the knowledge that stream was sorted already + */ + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .sorted() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .sorted() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain() { + return LongStream.range(0, size).parallel() + .sorted() + .sorted() + .sorted() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain() { + return LongStream.range(0, size).parallel() + .sorted() + .sorted() + .sorted() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for both sorted() and uniq() operations. + * Sorts long range modulo power of two, then does unique elements. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class SortedUnique { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + */ + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(1, size) + .map(l -> l & 0xFFFF) + .sorted() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(1, size).parallel() + .map(l -> l & 0xFFFF) + .sorted() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.ops.value; + +import org.openjdk.bench.java.util.stream.ops.LongAccumulator; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark for uniqueElements() operation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class UniqueElements { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + * - the result of applying consecutive operations is the same, in order to have the same number of elements in sink + */ + @Param("100000") + private int size; + + @Benchmark + public long seq_invoke() { + return LongStream.range(0, size) + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_invoke() { + return LongStream.range(0, size).parallel() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long seq_chain() { + return LongStream.range(0, size) + .distinct() + .distinct() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + + @Benchmark + public long par_chain() { + return LongStream.range(0, size).parallel() + .distinct() + .distinct() + .distinct() + .collect(LongAccumulator::new, LongAccumulator::add, LongAccumulator::merge).get(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.pipeline; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark tests the pipeline fusion abilities. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class PipelineParMultiple { + + @Param("100000") + private int size; + + @Benchmark + public long bulk_into_anon() { + return LongStream.range(0, size).parallel() + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> false) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + @Benchmark + public long bulk_into_named() { + LongPredicate t = (x) -> true; + LongPredicate f = (x) -> false; + return LongStream.range(0, size).parallel() + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(f) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + + @Benchmark + public long bulk_foreach_anon() { + LongAdder adder = new LongAdder(); + LongStream.range(0, size).parallel().forEach((l) -> { + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> false).test(l)) + adder.add(l); + }); + return adder.sum(); + } + + + @Benchmark + public long bulk_foreach_named() { + LongAdder adder = new LongAdder(); + LongPredicate t = (x) -> true; + LongPredicate f = (x) -> false; + LongStream.range(0, size).parallel().forEach((l) -> { + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (f.test(l)) + adder.add(l); + }); + return adder.sum(); + } + + @Benchmark + public long bulk_ifs() { + LongAdder adder = new LongAdder(); + LongStream.range(0, size).parallel().forEach((l) -> { + if (true) + if (true) + if (true) + if (true) + if (true) + if (true) + if (true) + if (false) + adder.add(l); + }); + return adder.sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.pipeline; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.LongPredicate; +import java.util.stream.LongStream; + +/** + * Benchmark tests the pipeline fusion abilities. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class PipelineSeqMultiple { + + @Param("100000") + private int size; + + @Benchmark + public Object bulk_into_anon() { + return LongStream.range(0, size) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> true) + .filter((x) -> false) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + @Benchmark + public Object bulk_into_named() { + LongPredicate t = (x) -> true; + LongPredicate f = (x) -> false; + return LongStream.range(0, size) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(t) + .filter(f) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + + @Benchmark + public Object bulk_foreach_anon() { + LongAdder adder = new LongAdder(); + LongStream.range(0, size).forEach((l) -> { + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> true).test(l)) + if (((LongPredicate) (x) -> false).test(l)) + adder.add(l); + }); + return adder.sum(); + } + + + @Benchmark + public Object bulk_foreach_named() { + LongAdder adder = new LongAdder(); + LongPredicate t = (x) -> true; + LongPredicate f = (x) -> false; + LongStream.range(0, size).forEach((l) -> { + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (t.test(l)) + if (f.test(l)) + adder.add(l); + }); + return adder.sum(); + } + + @Benchmark + public Object bulk_ifs() { + LongAdder adder = new LongAdder(); + LongStream.range(0, size).forEach((l) -> { + if (true) + if (true) + if (true) + if (true) + if (true) + if (true) + if (true) + if (false) + adder.add(l); + }); + return adder.sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.pipeline; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; + +/** + * Benchmark tests the pipeline construction costs. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class PipelineSetup { + + /** + * This is one of the few benchmarks where measuring running time makes sense. + */ + + @Param("100000") + private int size; + + @Benchmark + public Object baseline_newObject() { + return new Object(); + } + + @Benchmark + public LongStream seq_test00() { + return LongStream.range(0, size); + } + + @Benchmark + public LongStream seq_test01() { + return LongStream.range(0, size) + .filter((x) -> false); + } + + @Benchmark + public LongStream seq_test02() { + return LongStream.range(0, size) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream seq_test04() { + return LongStream.range(0, size) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream seq_test08() { + return LongStream.range(0, size) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream seq_test16() { + return LongStream.range(0, size) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream par_test00() { + return LongStream.range(0, size).parallel(); + } + + @Benchmark + public LongStream par_test01() { + return LongStream.range(0, size).parallel() + .filter((x) -> false); + } + + @Benchmark + public LongStream par_test02() { + return LongStream.range(0, size).parallel() + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream par_test04() { + return LongStream.range(0, size).parallel() + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream par_test08() { + return LongStream.range(0, size).parallel() + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + + @Benchmark + public LongStream par_test16() { + return LongStream.range(0, size).parallel() + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false) + .filter((x) -> false); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/Terminal.java b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/Terminal.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/pipeline/Terminal.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.pipeline; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Iterator; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.LongConsumer; +import java.util.stream.LongStream; + +/** + * Benchmark for forEach()/iterator()/into() operations; + * Testing which one is faster for semantically-equvalent operations. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Terminal { + + /** + * Implementation notes: + * - parallel version requires thread-safe sink, we use the same for sequential version for better comparison + * - operations are explicit inner classes to untangle unwanted lambda effects + */ + + @Param("100000") + private int size; + + private LongAdder sink; + private LongConsumer block; + + @Setup + public void setup() { + sink = new LongAdder(); + block = new LongConsumer() { + @Override + public void accept(long v) { + sink.add(v); + } + }; + } + + @Benchmark + public long baseline_prim_acc() { + long s = 0; + for (long l = 0L; l < size; l++) { + s += l; + } + sink.add(s); + return sink.sum(); + } + + @Benchmark + public long baseline_prim_sink() { + for (long l = 0L; l < size; l++) { + sink.add(l); + } + return sink.sum(); + } + + @Benchmark + public long baseline_iterator_acc() { + long s = 0; + for (Iterator iterator = LongStream.range(0, size).boxed().iterator(); iterator.hasNext(); ) { + Long l = iterator.next(); + s += l; + } + sink.add(s); + return sink.sum(); + } + + @Benchmark + public long baseline_iterator_sink() { + for (Iterator iterator = LongStream.range(0, size).boxed().iterator(); iterator.hasNext(); ) { + sink.add(iterator.next()); + } + return sink.sum(); + } + + @Benchmark + public long seq_iterator() { + Iterator i = LongStream.range(0, size).boxed().iterator(); + while (i.hasNext()) { + sink.add(i.next()); + } + return sink.sum(); + } + + @Benchmark + public long par_iterator() { + Iterator i = LongStream.range(0, size).parallel().boxed().iterator(); + while (i.hasNext()) { + sink.add(i.next()); + } + return sink.sum(); + } + + @Benchmark + public long seq_forEach() { + LongStream.range(1, size).forEach(block); + return sink.sum(); + } + + @Benchmark + public long par_forEach() { + LongStream.range(1, size).parallel().forEach(block); + return sink.sum(); + } + + @Benchmark + public long seq_into() { + return LongStream.range(1, size) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + @Benchmark + public long par_into() { + return LongStream.range(1, size).parallel() + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DataProviders.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DataProviders.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DataProviders.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) , Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.util.stream.tasks; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.stream.Stream; + +public class DataProviders { + public static Stream dictionary() throws IOException { + BufferedReader r = new BufferedReader(new InputStreamReader(DataProviders.class.getResourceAsStream("cmudict-0.7b.txt"))); + // Strip out the copyright notice and special chars + return r.lines().filter(w -> w.charAt(0) >= 'A' && w.charAt(0) <= 'Z').map(w -> w.substring(0, w.indexOf(" "))).onClose(() -> { + try { + r.close(); + } catch (IOException e) { + // swallow + } + }); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; +import java.util.function.Function; + + +/** + * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + @Setup(Level.Trial) + public void loadData() { + // cause classload and problem initialization + DictionaryProblem.class.getName(); + } + + @Benchmark + public int hm_seq() { + int max = 0; + for (String s : DictionaryProblem.get()) { + int v = DictionaryProblem.wordValue(s); + if (v > max) { + max = v; + } + } + return max; + } + + @Benchmark + public int hm_par() { + return new Task(DictionaryProblem.get(), 0, DictionaryProblem.get().length).invoke(); + } + + @Benchmark + public int bulk_seq_inner() { + return Arrays.stream(DictionaryProblem.get()) + .map(new Function() { + @Override + public Integer apply(String s) { + return DictionaryProblem.wordValue(s); + } + }) + .reduce(0, new BinaryOperator() { + @Override + public Integer apply(Integer l, Integer r) { + return l > r ? l : r; + } + }); + } + + @Benchmark + public int bulk_par_inner() { + return Arrays.stream(DictionaryProblem.get()).parallel() + .map(new Function() { + @Override + public Integer apply(String s) { + return DictionaryProblem.wordValue(s); + } + }) + .reduce(0, new BinaryOperator() { + @Override + public Integer apply(Integer l, Integer r) { + return l > r ? l : r; + } + }); + } + + + public static class Task extends RecursiveTask { + private static final int FORK_LIMIT = 500; + + private final String[] words; + private final int start, end; + + Task(String[] w, int start, int end) { + this.words = w; + this.start = start; + this.end = end; + } + + @Override + protected Integer compute() { + int size = end - start; + if (size > FORK_LIMIT) { + int mid = start + size / 2; + Task t1 = new Task(words, start, mid); + Task t2 = new Task(words, mid, end); + t1.fork(); + Integer v2 = t2.invoke(); + Integer v1 = t1.join(); + return Math.max(v1, v2); + } else { + int max = 0; + for (int i = start; i < end; i++) { + int v = DictionaryProblem.wordValue(words[i]); + if (v > max) { + max = v; + } + } + return max; + } + } + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; + +import org.openjdk.bench.java.util.stream.tasks.DataProviders; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class DictionaryProblem { + + private static final int DICTIONARY_REPEAT_RATE = 40; + + private static final String[] dict; + + static { + int size; + int idx = 0; + List d = Collections.emptyList(); + try (Stream s = DataProviders.dictionary()) { + d = s.collect(Collectors.toList()); + } catch (Exception e) { + // ignore + } + size = d.size() * DICTIONARY_REPEAT_RATE; + dict = new String[size]; + for (int i = 0; i < DICTIONARY_REPEAT_RATE; i++) { + d.sort(new IdxComparator(i)); + for (String s : d) { + // copy the whole string + dict[idx++] = new String(s.toCharArray()); + } + } + assert (idx == dict.length); + } + + public static String[] get() { + return dict; + } + + /** + * A word value is the sum of alphabet value of each characters in a word. + * + * @param word The word + * @return The word value + */ + public static int wordValue(String word) { + char[] ar = word.toLowerCase().toCharArray(); + int value = 0; + for (char c: ar) { + int v = c - 'a' + 1; + if (v < 1 || v > 26) { + // skip non-alphabet + continue; + } + value += (c - 'a' + 1); + } + return value; + } + + static class IdxComparator implements Comparator { + private final int index; + + public IdxComparator(int i) { + index = i; + } + + @Override + public int compare(String a, String b) { + if (a.length() > index && b.length() > index) { + return (a.charAt(index) - b.charAt(index)); + } else { + return (a.length() - b.length()); + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Lambda { + + @Setup(Level.Trial) + public void loadData() { + // cause classload and problem initialization + DictionaryProblem.class.getName(); + } + + public static Integer maxInt(Integer l, Integer r) { + return l > r ? l : r; + } + + @Benchmark + public int bulk_seq_lambda() { + return Arrays.stream(DictionaryProblem.get()) + .map(s -> DictionaryProblem.wordValue(s)) + .reduce(0, (l, r) -> l > r ? l : r); + } + + @Benchmark + public int bulk_seq_mref() { + return Arrays.stream(DictionaryProblem.get()) + .map(DictionaryProblem::wordValue) + .reduce(0, Lambda::maxInt); + } + + @Benchmark + public int bulk_par_lambda() { + return Arrays.stream(DictionaryProblem.get()).parallel() + .map(s -> DictionaryProblem.wordValue(s)) + .reduce(0, (l, r) -> l > r ? l : r); + } + + @Benchmark + public int bulk_par_mref() { + return Arrays.stream(DictionaryProblem.get()).parallel() + .map(DictionaryProblem::wordValue) + .reduce(0, Lambda::maxInt); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.DictionaryWordValue; + +/** + * Bulk scenario: searching max "wordValue" through the dictionary (array of strings). + */ +public class Xtras { + + // no workloads yet + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerDuplicate; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * This benchmark assesses flatMap() performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Bulk { + + /** + * Implementation notes: + * - parallel versions need to use special sink to get the values + */ + + private IntegerDuplicateProblem problem; + private LongAdder adder; + + @Setup + public void setup() { + problem = new IntegerDuplicateProblem(); + adder = new LongAdder(); + } + + @Benchmark + public long hm_seq() { + for (Integer i : problem.get()) { + adder.add(i); + adder.add(i); + } + return adder.sum(); + } + + @Benchmark + public long hm_par() { + new Task(problem.get(), adder, 0, problem.get().length).invoke(); + return adder.sum(); + } + + @Benchmark + public long bulk_seq_inner() { + return Arrays.stream(problem.get()).flatMap(new Function>() { + @Override + public Stream apply(Integer integer) { + return Collections.nCopies(2, integer).stream(); + } + }).collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + @Benchmark + public long bulk_par_inner() { + return Arrays.stream(problem.get()).parallel().flatMap(new Function>() { + @Override + public Stream apply(Integer integer) { + return Collections.nCopies(2, integer).stream(); + } + }).collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + public static class Task extends RecursiveAction { + private static final int FORK_LIMIT = 500; + + private final Integer[] data; + private final LongAdder sink; + private final int start; + private final int end; + + Task(Integer[] w, LongAdder sink, int start, int end) { + this.data = w; + this.sink = sink; + this.start = start; + this.end = end; + } + + @Override + protected void compute() { + int size = end - start; + if (size > FORK_LIMIT) { + int mid = start + size / 2; + Task t1 = new Task(data, sink, start, mid); + Task t2 = new Task(data, sink, mid, end); + t1.fork(); + t2.invoke(); + t1.join(); + } else { + for (int i = start; i < end; i++) { + sink.add(i); + sink.add(i); + } + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerDuplicate; + +import java.util.Random; + +public class IntegerDuplicateProblem { + + private static final int DATA_SIZE = Integer.getInteger("bench.problemSize", 10*1024*1024); + + private final Integer[] data = new Integer[DATA_SIZE]; + + public IntegerDuplicateProblem() { + // use fixed seed to reduce run-to-run variance + Random rand = new Random(0x30052012); + + for (int i = 0; i < data.length; i++) { + data[i] = new Integer(rand.nextInt()); + } + } + + public Integer[] get() { + return data; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerDuplicate; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; + +/** + * This benchmark assesses flatMap() performance. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class Lambda { + + /** + * Implementation notes: + * - parallel versions need to use special sink to get the values + */ + + private IntegerDuplicateProblem problem; + + @Setup + public void setup() { + problem = new IntegerDuplicateProblem(); + } + + @Benchmark + public long lambda_seq_inner() { + return Arrays.stream(problem.get()).flatMap(k -> Collections.nCopies(2, k).stream()) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + + @Benchmark + public long lambda_par_inner() { + return Arrays.stream(problem.get()).parallel().flatMap(k -> Collections.nCopies(2, k).stream()) + .collect(LongAdder::new, LongAdder::add, (la1, la2) -> la1.add(la2.sum())).sum(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerMax; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; + +/** + * Bulk scenario: search for max value in array. + * + * This test covers bulk infrastructure only. Refer to other tests for lambda-specific cases. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + private IntegerMaxProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new IntegerMaxProblem(); + } + + @Benchmark + public int hm_seq() { + int max = Integer.MIN_VALUE; + for (int v: problem.get()) { + if (v > max) { + max = v; + } + } + return max; + } + + @Benchmark + public int hm_par() { + return new MaxIntTask(problem.get(), 0, problem.get().length).invoke(); + } + + @Benchmark + public int bulk_seq_inner() { + return Arrays.stream(problem.get()).reduce(Integer.MIN_VALUE, new BinaryOperator() { + @Override + public Integer apply(Integer l, Integer r) { + return l > r ? l : r; + } + }); + } + + @Benchmark + public int bulk_par_inner() { + return Arrays.stream(problem.get()).parallel().reduce(Integer.MIN_VALUE, new BinaryOperator() { + @Override + public Integer apply(Integer l, Integer r) { + return l > r ? l : r; + } + }); + } + + static class MaxIntTask extends RecursiveTask { + private static final int FORK_LIMIT = 1000; + final Integer[] data; + final int start, end; + + MaxIntTask(Integer[] data, int start, int end) { + this.data = data; + this.start = start; + this.end = end; + } + + @Override + protected Integer compute() { + int size = end - start; + if (size > FORK_LIMIT) { + int mid = start + size / 2; + MaxIntTask t1 = new MaxIntTask(data, start, mid); + MaxIntTask t2 = new MaxIntTask(data, mid, end); + t1.fork(); + Integer v2 = t2.invoke(); + Integer v1 = t1.join(); + return Math.max(v1, v2); + } else { + int max = Integer.MIN_VALUE; + for (int i = start; i < end; i++) { + if (data[i] > max) { + max = data[i]; + } + } + return max; + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerMax; + +import java.util.Random; + +public class IntegerMaxProblem { + + private static final int DATA_SIZE = Integer.getInteger("bench.problemSize", 10*1024*1024); + + private final Integer[] data = new Integer[DATA_SIZE]; + + public IntegerMaxProblem() { + // use fixed seed to reduce run-to-run variance + Random rand = new Random(0x30052012); + + for (int i = 0; i < data.length; i++) { + data[i] = new Integer(rand.nextInt()); + } + } + + public Integer[] get() { + return data; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerMax; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * Bulk scenario: search for max value in array. + * + * This test covers lambda-specific solutions for the problem. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Lambda { + + private IntegerMaxProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new IntegerMaxProblem(); + } + + public static Integer maxInt(Integer l, Integer r) { + return l > r ? l : r; + } + + @Benchmark + public int bulk_seq_lambda() { + return Arrays.stream(problem.get()).reduce(Integer.MIN_VALUE, (l, r) -> l > r ? l : r); + } + + @Benchmark + public int bulk_seq_methodRef() { + return Arrays.stream(problem.get()).reduce(Integer.MIN_VALUE, Lambda::maxInt); + } + + @Benchmark + public int bulk_par_lambda() { + return Arrays.stream(problem.get()).parallel().reduce(Integer.MIN_VALUE, (l, r) -> l > r ? l : r); + } + + @Benchmark + public int bulk_par_methodRef() { + return Arrays.stream(problem.get()).parallel().reduce(Integer.MIN_VALUE, Lambda::maxInt); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerMax; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Bulk scenario: search for max value in array. + * + * This test covers other interesting solutions for the original problem. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Xtras { + + private IntegerMaxProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new IntegerMaxProblem(); + } + + +// @Benchmark +// public int bulk_seq_inner_pull() { +// Stream stream = Arrays.stream(problem.get()); +// +// // force pull traversal +// Integer car = stream.iterator().next(); +// Integer cdr = stream.reduce(Integer.MIN_VALUE, new BinaryOperator() { +// @Override +// public Integer apply(Integer l, Integer r) { +// return l > r ? l : r; +// } +// }); +// return (car > cdr) ? car : cdr; +// } +// +// @Benchmark +// public int bulk_par_inner_pull() { +// Stream stream = Arrays.parallelStream(problem.get()); +// +// // force pull traversal +// Integer car = stream.iterator().next(); +// Integer cdr = stream.reduce(Integer.MIN_VALUE, new BinaryOperator() { +// @Override +// public Integer apply(Integer l, Integer r) { +// return l > r ? l : r; +// } +// }); +// return (car > cdr) ? car : cdr; +// } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerSum; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; + +/** + * Bulk scenario: compute the sum of Integer array. + * + * This test covers bulk infrastructure only. Refer to other tests for lambda-specific cases. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + private IntegerSumProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new IntegerSumProblem(); + } + + @Benchmark + public int hm_seq() { + int sum = 0; + for (int v : problem.get()) { + sum += v; + } + return sum; + } + + @Benchmark + public int hm_par() { + return new SumIntTask(problem.get()).invoke(); + } + + @Benchmark + public int bulk_seq_inner() { + return Arrays.stream(problem.get()).reduce(0, new BinaryOperator() { + @Override + public Integer apply(Integer left, Integer right) { + return left + right; + } + }); + } + + @Benchmark + public int bulk_par_inner() { + return Arrays.stream(problem.get()).parallel().reduce(0, new BinaryOperator() { + @Override + public Integer apply(Integer left, Integer right) { + return left + right; + } + }); + } + + static class SumIntTask extends RecursiveTask { + private static final int FORK_LIMIT = 1000; + final Integer[] data; + final int start, end; + + SumIntTask(Integer[] data) { + this(data, 0, data.length); + } + + SumIntTask(Integer[] data, int start, int end) { + this.data = data; + this.start = start; + this.end = end; + } + + @Override + protected Integer compute() { + int size = end - start; + if (size > FORK_LIMIT) { + int mid = start + size / 2; + SumIntTask t1 = new SumIntTask(data, start, mid); + SumIntTask t2 = new SumIntTask(data, mid, end); + t1.fork(); + return t2.invoke() + t1.join(); + } else { + int sum = 0; + for (int i = start; i < end; i++) { + sum += data[i]; + } + return sum; + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerSum; + +import java.util.Random; + +public class IntegerSumProblem { + + private static final int DATA_SIZE = Integer.getInteger("bench.problemSize", 10*1024*1024); + + private final Integer[] data = new Integer[DATA_SIZE]; + + public IntegerSumProblem() { + // use fixed seed to reduce run-to-run variance + Random rand = new Random(0x30052012); + + for (int i = 0; i < data.length; i++) { + data[i] = new Integer(rand.nextInt()); + } + } + + public Integer[] get() { + return data; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerSum; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * Bulk scenario: compute the sum of Integer array. + * + * This test covers lambda-specific solutions for the problem. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Lambda { + + private IntegerSumProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new IntegerSumProblem(); + } + + public static Integer sum(Integer a, Integer b) { + return a + b; + } + + @Benchmark + public int bulk_seq_lambda() { + return Arrays.stream(problem.get()).reduce(0, (l, r) -> l + r); + } + + @Benchmark + public int bulk_par_lambda() { + return Arrays.stream(problem.get()).parallel().reduce(0, (l, r) -> l + r); + } + + @Benchmark + public int bulk_seq_mref() { + return Arrays.stream(problem.get()).reduce(0, Lambda::sum); + } + + @Benchmark + public int bulk_par_mref() { + return Arrays.stream(problem.get()).parallel().reduce(0, Lambda::sum); + } + + @Benchmark + public int bulk_seq_Integer_mref() { + return Arrays.stream(problem.get()).reduce(0, Integer::sum); + } + + @Benchmark + public int bulk_par_Integer_mref() { + return Arrays.stream(problem.get()).parallel().reduce(0, Integer::sum); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.IntegerSum; + +/** + * Bulk scenario: compute the sum of Integer array. + * + * This test covers other interesting solutions for the original problem. + */ +public class Xtras { + + // no workloads yet + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) , Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.util.stream.tasks.PhoneCode; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.openjdk.bench.java.util.stream.tasks.PhoneCode.PhoneCodeProblem.wordsForNumber; + +/** + * This benchmark compare various strategies solving the phone code problem. + * The result should offer some insights on strength/drawbacks of underlying + * implementation. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Benchmark) +public class Bulk { + // several method choke up with 6-digit problem + private final static int SIZE = 5; + private Stream join(String head, + String tail, + Function> encoder) + { + Stream s = wordsForNumber(head).stream(); + + if (! tail.isEmpty()) { + s = s.flatMap(h -> encoder.apply(tail).map(t -> h + " " + t)); + } + + return s; + } + + private Stream encode_par1(String number) { + return IntStream.range(1, number.length() + 1) + .parallel() + .boxed() + .flatMap(i -> join(number.substring(0, i), + number.substring(i), + this::encode_par1)); + } + + private Stream encode_par2(String number) { + return IntStream.range(1, number.length() + 1) + .boxed() + .parallel() + .flatMap(i -> join(number.substring(0, i), + number.substring(i), + this::encode_par2)); + } + + private Stream encode_ser(String number) { + return IntStream.range(1, number.length() + 1) + .boxed() + .flatMap(i -> join(number.substring(0, i), + number.substring(i), + this::encode_ser)); + } + + private Stream encode_loop_concat(String number) { + if (number.isEmpty()) { + return Stream.empty(); + } + // full number + Stream s = wordsForNumber(number).stream(); + // split + for (int i = 1; i < number.length(); i++) { + s = Stream.concat(s, join(number.substring(0, i), + number.substring(i), + this::encode_loop_concat)); + } + + return s; + } + + private Collection encode_loop_collect(String number) { + if (number.isEmpty()) { + return Collections.emptySet(); + } + + Collection rv = new HashSet<>(); + + for (int i = 1; i <= number.length(); i++) { + join(number.substring(0, i), + number.substring(i), + s -> encode_loop_collect(s).stream()).forEach(rv::add); + } + + return rv; + } + + private Collection encode_inline(String number) { + if (number.isEmpty()) { + return Collections.emptySet(); + } + + Collection rv = new HashSet<>(); + + for (int i = 1; i < number.length(); i++) { + String front = number.substring(0, i); + String rest = number.substring(i); + wordsForNumber(front).stream() + .flatMap(h -> encode_inline(rest).stream().map(t -> h + " " + t)) + .forEach(rv::add); + } + + rv.addAll(wordsForNumber(number)); + + return rv; + } + + @Benchmark + public int bulk_par_range_concurrent() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_par1) + .collect(Collectors.toConcurrentMap( + Function.identity(), + Function.identity(), + (l, r) -> l)) + .keySet() + .size(); + } + + @Benchmark + public int bulk_par_boxed_range_concurrent() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_par2) + .collect(Collectors.toConcurrentMap( + Function.identity(), + Function.identity(), + (l, r) -> l)) + .keySet() + .size(); + } + + @Benchmark + public int bulk_par_range() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_par1) + .collect(Collectors.toSet()) + .size(); + } + + @Benchmark + public int bulk_par_boxed_range() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_par2) + .collect(Collectors.toSet()) + .size(); + } + + @Benchmark + public int bulk_ser_range() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_ser) + .collect(Collectors.toSet()) + .size(); + } + + @Benchmark + public int bulk_ser_loop_concat() { + // force collect + return PhoneCodeProblem.get(SIZE) + .flatMap(this::encode_loop_concat) + .collect(Collectors.toSet()) + .size(); + } + + @Benchmark + public int bulk_ser_loop_collect() { + return PhoneCodeProblem.get(SIZE) + .map(this::encode_loop_collect) + .map(Collection::size) + .reduce(0, Integer::sum); + } + + @Benchmark + public int bulk_ser_inline() { + return PhoneCodeProblem.get(SIZE) + .map(this::encode_inline) + .map(Collection::size) + .reduce(0, Integer::sum); + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.util.stream.tasks.PhoneCode; + +import org.openjdk.bench.java.util.stream.tasks.DataProviders; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * The phone coder problem is trying to find full list of possible + * mnemonic combination of numbers. + * + * The solution is based on Martin Odersky's devoxx 2010 scala talk, + * where numbers are not allowed in the result, which is not really + * correct, but we don't care. + */ +public class PhoneCodeProblem { + // Map Character 'A'-'Z' to digits "2"-"9", key is charCode + private static final Map CHAR_CODE; + // Map a string of digits to a collection of dictionary words + private static final Map> WORD_CODES; + + static { + HashMap mnemonics = new HashMap<>(8); + mnemonics.put("2", "ABC"); + mnemonics.put("3", "DEF"); + mnemonics.put("4", "GHI"); + mnemonics.put("5", "JKL"); + mnemonics.put("6", "MNO"); + mnemonics.put("7", "PQRS"); + mnemonics.put("8", "TUV"); + mnemonics.put("9", "WXYZ"); + + CHAR_CODE = new ConcurrentHashMap<>(); + mnemonics.entrySet().stream().forEach(e -> + e.getValue().chars().forEach(c -> + { CHAR_CODE.put(c, e.getKey()); } )); + + WORD_CODES = loadDictionary(); + // System.out.println("Dictionary loaded with " + WORD_CODES.size() + " number entries"); + } + + // Convert a word to its number form + private static String wordToNumber(String word) { + return word.chars().mapToObj(CHAR_CODE::get) + .reduce("", String::concat); + } + + // Prepare number -> word lookup table + private static Map> loadDictionary() { + try (Stream s = DataProviders.dictionary()) { + return s.filter(w -> w.length() > 1) + .filter(w -> w.matches("[a-zA-Z]*")) + .map(String::toUpperCase) + .collect(Collectors.groupingBy(PhoneCodeProblem::wordToNumber)); + } catch (Exception ex) { + ex.printStackTrace(System.err); + return Collections.emptyMap(); + } + } + + public static Collection wordsForNumber(String number) { + Collection rv = WORD_CODES.get(number); + return (null == rv) ? Collections.emptySet() : rv; + } + + public static Stream get(int length) { + String digits[] = { "2", "3", "4", "5", "6", "7", "8", "9" }; + + Stream s = Arrays.stream(digits); + for (int i = 1; i < length; i++) { + s = s.flatMap(d1 -> Arrays.stream(digits).map(d2 -> d1 + d2)); + } + return s; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter; + +import java.util.ArrayList; +import java.util.List; + +public class PrimesProblem { + + /** + * Factors n into its prime factors. If n is prime, + * the result is a list of length 1 containing n. + * + * @param n the number to be factored + * @return a list of prime factors + */ + static List factor(long n) { + List flist = new ArrayList<>(); + + while (n % 2L == 0) { + flist.add(2L); + n /= 2L; + } + + long divisor = 3L; + while (n > 1L) { + long quotient = n / divisor; + if (n % divisor == 0) { + flist.add(divisor); + n = quotient; + } else if (quotient > divisor) { + divisor += 2L; + } else { + flist.add(n); + break; + } + } + + return flist; + } + + /** + * Tests whether n is prime. + * + * @param n the number to be tested + * @return true if n is prime, false if n is composite + */ + public static boolean isPrime(long n) { + List factors = factor(n); + return (factors.size() == 1); + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t100; + +import org.openjdk.bench.java.util.stream.tasks.PrimesFilter.PrimesProblem; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + @Benchmark + public List hm_seq() { + List results = new ArrayList<>(); + for (long i = RANGE_START; i < RANGE_END; i++) { + if (PrimesProblem.isPrime(i)) { + results.add(i); + } + } + return results; + } + + @Benchmark + public List hm_par() { + return new FactoringTask(RANGE_START, RANGE_END).invoke(); + } + + @Benchmark + public List bulk_seq_inner() { + return LongStream.range(RANGE_START, RANGE_END) + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_inner() { + return LongStream.range(RANGE_START, RANGE_END).parallel() + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_inner() { + return LongStream.range(RANGE_START, RANGE_END).parallel() + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).sequential().collect(Collectors.toList()); + } + + public static class FactoringTask extends RecursiveTask> { + final long low; + final long high; + + @Override + protected List compute() { + if (high - low == 1L) { + if (PrimesProblem.isPrime(low)) + return Collections.singletonList(low); + else + return Collections.emptyList(); + } + + long mid = (low + high) / 2L; + FactoringTask t1 = new FactoringTask(low, mid); + FactoringTask t2 = new FactoringTask(mid, high); + + List results; + + // The right way to do it. Forks off one task and + // continues the other task in this thread. I've + // seen up to 8x speed up on 16-way Intel and 32-way + // SPARC boxes (which probably matches the actual number + // of cores they have, as opposed to the number of threads) + t2.fork(); + results = new ArrayList<>(t1.compute()); + results.addAll(t2.join()); + + return results; + } + + FactoringTask(long low, long high) { + this.low = low; + this.high = high; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t100; + +import org.openjdk.bench.java.util.stream.tasks.PrimesFilter.PrimesProblem; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Lambda { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + @Benchmark + public List bulk_seq_lambda() { + return LongStream.range(RANGE_START, RANGE_END).boxed().filter(n -> PrimesProblem.isPrime(n)).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_seq_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).boxed().filter(PrimesProblem::isPrime).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_lambda() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(n -> PrimesProblem.isPrime(n)).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(PrimesProblem::isPrime).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_lambda() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(n -> PrimesProblem.isPrime(n)).sequential().collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(PrimesProblem::isPrime).sequential().collect(Collectors.toList()); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t100; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +public class Xtras { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + /** No code yet **/ + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t10000; + +import org.openjdk.bench.java.util.stream.tasks.PrimesFilter.PrimesProblem; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + @Benchmark + public List hm_seq() { + List results = new ArrayList<>(); + for (long i = RANGE_START; i < RANGE_END; i++) { + if (PrimesProblem.isPrime(i)) { + results.add(i); + } + } + return results; + } + + @Benchmark + public List hm_par() { + return new FactoringTask(RANGE_START, RANGE_END).invoke(); + } + + @Benchmark + public List bulk_seq_inner() { + return LongStream.range(RANGE_START, RANGE_END).parallel() + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_inner() { + return LongStream.range(RANGE_START, RANGE_END).parallel() + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_inner() { + return LongStream.range(RANGE_START, RANGE_END).parallel() + .boxed() + .filter(new Predicate() { + @Override + public boolean test(Long o) { + return PrimesProblem.isPrime(o); + } + } + ).sequential().collect(Collectors.toList()); + } + + public static class FactoringTask extends RecursiveTask> { + final long low; + final long high; + + @Override + protected List compute() { + if (high - low == 1L) { + if (PrimesProblem.isPrime(low)) + return Collections.singletonList(low); + else + return Collections.emptyList(); + } + + long mid = (low + high) / 2L; + FactoringTask t1 = new FactoringTask(low, mid); + FactoringTask t2 = new FactoringTask(mid, high); + + List results; + + // The right way to do it. Forks off one task and + // continues the other task in this thread. I've + // seen up to 8x speed up on 16-way Intel and 32-way + // SPARC boxes (which probably matches the actual number + // of cores they have, as opposed to the number of threads) + t2.fork(); + results = new ArrayList<>(t1.compute()); + results.addAll(t2.join()); + + return results; + } + + FactoringTask(long low, long high) { + this.low = low; + this.high = high; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t10000; + +import org.openjdk.bench.java.util.stream.tasks.PrimesFilter.PrimesProblem; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Lambda { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + @Benchmark + public List bulk_seq_lambda() { + return LongStream.range(RANGE_START, RANGE_END).boxed().filter(n -> PrimesProblem.isPrime(n)).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_seq_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).boxed().filter(PrimesProblem::isPrime).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_lambda() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(n -> PrimesProblem.isPrime(n)).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_par_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(PrimesProblem::isPrime).collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_lambda() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(n -> PrimesProblem.isPrime(n)).sequential().collect(Collectors.toList()); + } + + @Benchmark + public List bulk_parseq_methodRef() { + return LongStream.range(RANGE_START, RANGE_END).parallel().boxed().filter(PrimesProblem::isPrime).sequential().collect(Collectors.toList()); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesFilter.t10000; + +/** + * This benchmark evaluates find all prime numbers in a range. + * + * filter()...into() actions are benchmarked. + */ +public class Xtras { + + private final long RANGE_START = 1000_000_000_000_000L; + private final long RANGE_END = RANGE_START + 100; + + /** No code yet **/ + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesSieve; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Arrays; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; +import java.util.function.Predicate; + +/** + * Bulk scenario: filter out candidate primes. + * + * This test covers bulk infrastructure only. Refer to other tests for lambda-specific cases. + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class Bulk { + + private PrimesSieveProblem problem; + + @Setup(Level.Trial) + public void populateData(){ + problem = new PrimesSieveProblem(); + } + + @Benchmark + public int hm_seq() { + int max = Integer.MIN_VALUE; + for (int d : problem.get()) { + if (PrimesSieveProblem.isNotDivisible(d, 2) + && PrimesSieveProblem.isNotDivisible(d, 3) + && PrimesSieveProblem.isNotDivisible(d, 5) + && PrimesSieveProblem.isNotDivisible(d, 7) + && PrimesSieveProblem.isNotDivisible(d, 11) + && PrimesSieveProblem.isNotDivisible(d, 13) + && PrimesSieveProblem.isNotDivisible(d, 17) + && PrimesSieveProblem.isNotDivisible(d, 19) + ) { + if (d > max) { + max = d; + } + } + } + return max; + } + + @Benchmark + public int hm_par() { + return new FilterTask(problem.get()).invoke(); + } + + @Benchmark + public int bulk_seq_inner() { + return Arrays.stream(problem.get()) + .filter(new FilterOp(2)) + .filter(new FilterOp(3)) + .filter(new FilterOp(5)) + .filter(new FilterOp(7)) + .filter(new FilterOp(11)) + .filter(new FilterOp(13)) + .filter(new FilterOp(17)) + .filter(new FilterOp(19)) + .reduce(Integer.MIN_VALUE, new ReduceOp()); + } + + @Benchmark + public int bulk_par_inner() { + return Arrays.stream(problem.get()).parallel() + .filter(new FilterOp(2)) + .filter(new FilterOp(3)) + .filter(new FilterOp(5)) + .filter(new FilterOp(7)) + .filter(new FilterOp(11)) + .filter(new FilterOp(13)) + .filter(new FilterOp(17)) + .filter(new FilterOp(19)) + .reduce(Integer.MIN_VALUE, new ReduceOp()); + } + + static class FilterOp implements Predicate { + private final int divisor; + + public FilterOp(int divisor) { + this.divisor = divisor; + } + + @Override + public boolean test(Integer value) { + return PrimesSieveProblem.isNotDivisible(value, divisor); + } + } + + static class ReduceOp implements BinaryOperator { + @Override + public Integer apply(Integer left, Integer right) { + return (left > right) ? left : right; + } + } + + static class FilterTask extends RecursiveTask { + private static final int FORK_LIMIT = 1000; + final Integer[] data; + final int start, end; + + FilterTask(Integer[] data) { + this(data, 0, data.length); + } + + FilterTask(Integer[] data, int start, int end) { + this.data = data; + this.start = start; + this.end = end; + } + + @Override + protected Integer compute() { + int size = end - start; + if (size > FORK_LIMIT) { + int mid = start + size / 2; + FilterTask t1 = new FilterTask(data, start, mid); + FilterTask t2 = new FilterTask(data, mid, end); + t1.fork(); + Integer r1 = t2.invoke(); + Integer r2 = t1.join(); + return (r1 > r2) ? r1 : r2; + } else { + int max = Integer.MIN_VALUE; + for (int i = start; i < end; i++) { + int d = data[i]; + if (PrimesSieveProblem.isNotDivisible(d, 2) + && PrimesSieveProblem.isNotDivisible(d, 3) + && PrimesSieveProblem.isNotDivisible(d, 5) + && PrimesSieveProblem.isNotDivisible(d, 7) + && PrimesSieveProblem.isNotDivisible(d, 11) + && PrimesSieveProblem.isNotDivisible(d, 13) + && PrimesSieveProblem.isNotDivisible(d, 17) + && PrimesSieveProblem.isNotDivisible(d, 19) + ) { + if (d > max) { + max = d; + } + } + } + return max; + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.stream.tasks.PrimesSieve; + +public class PrimesSieveProblem { + + private static final int DATA_SIZE = Integer.getInteger("bench.problemSize", 10*1024); + + private final Integer[] data = new Integer[DATA_SIZE]; + + public PrimesSieveProblem() { + for (int i = 0; i < data.length; i++) { + data[i] = i; + } + } + + public Integer[] get() { + return data; + } + + public static boolean isNotDivisible(int i, int d) { + return (i % d) != 0; + } +} diff --git a/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/README b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/README new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/java/util/stream/tasks/README @@ -0,0 +1,55 @@ +Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 only, as +published by the Free Software Foundation. Oracle designates this +particular file as subject to the "Classpath" exception as provided +by Oracle in the LICENSE file that accompanied this code. + +This code is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +version 2 for more details (a copy is included in the LICENSE file that +accompanied this code). + +You should have received a copy of the GNU General Public License version +2 along with this work; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +or visit www.oracle.com if you need additional information or have any +questions. + +======================================================================= + +The tests are divided by scenario. + +Each scenario has the problem it tries to solve, and it does that with several options: + - BulkBench only compares handmade solutions vs. JDK bulk operations, without resorting to lambdas/methodrefs + - LambdaBench does bulk operations with lambdas/methodrefs + - XtrasBench has some other interesting options + +All tests in these benchmarks follow the following naming convention. +Test names is the concatenation of several markers: + +{hm|bulk}: infrastructure used + - hm: "handmade" version which users would presumably implement otherwise + - bulk: JDK8-ish bulk operation + +{seq|par}: parallelism mode + - seq: sequential mode + - par: parallel mode; in "hm" case, this might have different implementations + +{.|inner|lambda|mref}: functional interface type + - .: no specific meaning + - inner: explicit inner class + - lambda: JDK8-ish lambda + - mref: JDK8-ish method ref + +E.g. bulk_seq_inner is the test harnesses JDK8 bulk operations in sequential mode, and explicit inner class as function + +All benchmarks should be executed in the following modes (see -t harness cmdline option): + - single mode (thread = 1), + - core mode (thread = number of cores), + - max mode (thread = number of HW threads). diff --git a/test/micro/classes/org/openjdk/bench/javax/crypto/AES.java b/test/micro/classes/org/openjdk/bench/javax/crypto/AES.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/crypto/AES.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.crypto; + +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +public class AES { + + @Param("10000000") + private int count; + + private Cipher cipher; + private byte[] src; + + @Setup + public void setup() throws Exception { + SecretKeySpec keySpec = new SecretKeySpec(new byte[]{-80, -103, -1, 68, -29, -94, 61, -52, 93, -59, -128, 105, 110, 88, 44, 105}, "AES"); + IvParameterSpec iv = new IvParameterSpec(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); + + src = new byte[count]; + new Random(1).nextBytes(src); + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UnlockDiagnosticVMOptions", "-XX:-UseAES", "-XX:-UseAESIntrinsics"}) + public byte[] testBaseline() throws Exception { + return cipher.doFinal(src); + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+UseAES", "-XX:-UseAESIntrinsics"}) + public byte[] testUseAes() throws Exception { + return cipher.doFinal(src); + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+UseAES", "-XX:+UseAESIntrinsics"}) + public byte[] testUseAesIntrinsics() throws Exception { + return cipher.doFinal(src); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/javax/crypto/Crypto.java b/test/micro/classes/org/openjdk/bench/javax/crypto/Crypto.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/crypto/Crypto.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.crypto; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Tests various encryption algorithms with the JCE framework. Sets Fork + * parameters as these tests are rather allocation intensive. Reduced numbers of + * forks and iteration as benchmarks are stable. + */ +@State(Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +@Fork(jvmArgsAppend = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 5) +public class Crypto { + + @Param({"64", "1024", "16384"}) + private int length; + + @Param({"AES", "Blowfish", "DES", "DESede"}) + private String cipherName; + + private SecretKeySpec secretKey; + private Cipher encryptCipher; + private Cipher decryptCipher; + private byte[] plainBytes; + private byte[] encryptedBytes; + + @Setup + public void setupSubclass() throws NoSuchAlgorithmException, NoSuchPaddingException, + InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + + // Setup ciphers for encrypt/decrypt + byte[] encodedKey = KeyGenerator.getInstance(cipherName).generateKey().getEncoded(); + secretKey = new SecretKeySpec(encodedKey, cipherName); + + encryptCipher = Cipher.getInstance(cipherName); + encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey); + + decryptCipher = Cipher.getInstance(cipherName); + decryptCipher.init(Cipher.DECRYPT_MODE, secretKey); + + // Generate data to encrypt/decrypt + plainBytes = new byte[length]; + new Random(1234567890).nextBytes(plainBytes); + encryptedBytes = encryptCipher.doFinal(plainBytes); + } + + /** + * Encrypt byte array + * + * @return encrypted byte array + * @throws javax.crypto.IllegalBlockSizeException + * @throws javax.crypto.BadPaddingException + */ + @Benchmark + public byte[] encrypt() throws IllegalBlockSizeException, BadPaddingException { + return encryptCipher.doFinal(plainBytes); + } + + /** + * Decrypt byte array + * + * @return decrypted byte array + * @throws javax.crypto.IllegalBlockSizeException + * @throws javax.crypto.BadPaddingException + */ + @Benchmark + public byte[] decrypt() throws IllegalBlockSizeException, BadPaddingException { + return decryptCipher.doFinal(encryptedBytes); + } +} diff --git a/test/micro/classes/org/openjdk/bench/javax/tools/Javac.java b/test/micro/classes/org/openjdk/bench/javax/tools/Javac.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/tools/Javac.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.tools; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import javax.tools.JavaCompiler; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class Javac { + private List compilationUnits; + private JavaCompiler compiler; + private StandardJavaFileManager fileManager; + + @Setup + public void prepare() { + String helloWorld = "class Apan { \n" + " public static void main(String args[]) {\n" + + " System.out.println(\"hej apa\");\n" + " }\n" + "}\n"; + + compiler = ToolProvider.getSystemJavaCompiler(); + fileManager = compiler.getStandardFileManager(null, null, null); + compilationUnits = new ArrayList<>(); + compilationUnits.add(new JavaSourceFromString("Apan", helloWorld)); + } + + @Benchmark + public Boolean testCompile() throws Exception { + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits); + return task.call(); + } + + private static class JavaSourceFromString extends SimpleJavaFileObject { + final String code; + + JavaSourceFromString(String name, String code) { + super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), + Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/javax/xml/AbstractXMLMicro.java b/test/micro/classes/org/openjdk/bench/javax/xml/AbstractXMLMicro.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/xml/AbstractXMLMicro.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.xml; + +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Abstract base class with functionality and constants used by the XML micros. + */ +@State(Scope.Benchmark) +public abstract class AbstractXMLMicro { + + public static final String BUILDIMPL = "build-impl.xml"; + public static final String LOGCOMP = "log_comp.xml"; + public static final String MESSAGE12 = "message_12.xml"; + public static final String MSGATTACH = "msgAttach.xml"; + public static final String REZ = "reZ003vExc23082309.xml"; + + protected static final ConcurrentHashMap byteCache = new ConcurrentHashMap<>(); + + @Param({BUILDIMPL,LOGCOMP,MESSAGE12,MSGATTACH,REZ}) + protected String doc; + + /** + * Gets a given InputStream as a byte-array. + * + * @param is stream to read from + * @return byte-array + * @throws IOException if things go crazy-crazy + */ + private static byte[] getBytes(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + + int available = is.available(); + while (available > 0) { + int read = Math.min(b.length, available); + + int actuallyRead = is.read(b, 0, read); + baos.write(b, 0, actuallyRead); + + available = is.available(); + } + + is.close(); + byte array[] = baos.toByteArray(); + baos.close(); + + return array; + } + + /** + * Gets a given resource as a byte-array. + * + * @param name resource to fetch + * @return byte-array + * @throws IOException if things go crazy-crazy + * @throws URISyntaxException if resource given doesn't match syntax + */ + protected byte[] getFileBytesFromResource(String name) throws IOException, URISyntaxException { + byte[] bytes = byteCache.get(name); + if (bytes == null) { + bytes = getBytes(this.getClass().getResourceAsStream("/" + + AbstractXMLMicro.class.getPackage().getName().replace(".", "/") + + "/" + name)); + byteCache.put(name, bytes); + } + return bytes; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/javax/xml/DOM.java b/test/micro/classes/org/openjdk/bench/javax/xml/DOM.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/xml/DOM.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.xml; + +import org.openjdk.jmh.annotations.Benchmark; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class DOM extends AbstractXMLMicro { + + @Benchmark + public Document testBuild() throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + byte[] bytes = getFileBytesFromResource(doc); + InputSource source = new InputSource(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + + source.setByteStream(bais); + return buildDocument(dbf, source); + } + + @Benchmark + public Document testModify() throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + byte[] bytes = getFileBytesFromResource(doc); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + InputSource source = new InputSource(bais); + Document doc1 = buildDocument(dbf, source); + + modifyElementRecursive(doc1.getDocumentElement()); + return doc1; + } + + @Benchmark + public Document testWalk() throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + byte[] bytes = getFileBytesFromResource(doc); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + InputSource source = new InputSource(bais); + Document doc1 = buildDocument(dbf, source); + + walkElementRecursive(doc1.getDocumentElement()); + return doc1; + } + + private Document buildDocument(DocumentBuilderFactory dbf, InputSource source) + throws ParserConfigurationException, SAXException, IOException { + dbf.setValidating(false); + dbf.setNamespaceAware(true); + DocumentBuilder docBuilder = dbf.newDocumentBuilder(); + return docBuilder.parse(source); + } + + // TODO Fix so it isn't recursive? + private static void walkElementRecursive(Element element) { + // loop through children + if (element.hasChildNodes()) { + Node child = element.getFirstChild(); + while (child != null) { + + // handle child by type + int type = child.getNodeType(); + if (type == Node.ELEMENT_NODE) { + walkElementRecursive((Element) child); + } + child = child.getNextSibling(); + } + } + } + + // TODO Fix so it isn't recursive? + private void modifyElementRecursive(Element element) { + + // check for children present + if (element.hasChildNodes()) { + + // loop through child nodes + boolean content = false; + + // Should not be null since we already have made a .hasChildNodes() + // check. + Node child = element.getFirstChild(); + + do { + // Handle child by node type. + if (child.getNodeType() == Node.TEXT_NODE) { + String trimmed = child.getNodeValue().trim(); + if (trimmed.length() == 0) { + // delete child if nothing but whitespace + element.removeChild(child); + } else { + // make sure we have the parent element information + content = true; + Document doc = element.getOwnerDocument(); + String uri = element.getNamespaceURI(); + String prefix = element.getPrefix(); + content = true; + + // Create a "text" element matching parent namespace. + Element text = (uri == null) ? doc.createElement("text") : doc.createElementNS(uri, prefix + + ":text"); + + // wrap the trimmed content with new element + text.appendChild(doc.createTextNode(trimmed)); + element.replaceChild(text, child); + + } + } else if (child.getNodeType() == Node.ELEMENT_NODE) { + modifyElementRecursive((Element) child); + } + + } while ((child = child.getNextSibling()) != null); + + // check if we've seen any non-whitespace content for element + if (content) { + String prefix = element.getPrefix(); + String uri = element.getNamespaceURI(); + // add attribute flagging content found + if (prefix == null || prefix.length() == 0) { + element.setAttribute("text", "true"); + } else { + element.setAttributeNS(uri, prefix + ":text", "true"); + } + + } + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/javax/xml/SAXUsingJDK.java b/test/micro/classes/org/openjdk/bench/javax/xml/SAXUsingJDK.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/xml/SAXUsingJDK.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.xml; + +import org.openjdk.jmh.annotations.Benchmark; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.ByteArrayInputStream; + +/** + * Micro testing SAXParser performance using the JDK classes + */ +public class SAXUsingJDK extends AbstractXMLMicro { + + @Benchmark + public XMLReader testParse() throws Exception { + SAXParserFactory spf = SAXParserFactory.newInstance(); + byte[] bytes = getFileBytesFromResource(doc); + spf.setValidating(false); + SAXParser parser = spf.newSAXParser(); + XMLReader reader = parser.getXMLReader(); + InputSource source = new InputSource(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + + source.setByteStream(bais); + reader.parse(source); + return reader; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/javax/xml/STAX.java b/test/micro/classes/org/openjdk/bench/javax/xml/STAX.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/javax/xml/STAX.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.javax.xml; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.TearDown; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +public class STAX extends AbstractXMLMicro { + + /** Live data */ + public Map> liveData; + + @Setup(Level.Iteration) + public void setupLiveData() { + Map> map = new HashMap<>(); + // Somewhere around 100 MB live, but fragmented to start with. + for (int i = 0; i < 1000; i++) { + LinkedList list = new LinkedList<>(); + String key = "Dummy linked list " + i; + list.add(key); + for (int j = 0; j < 1000; j++) { + list.add("Dummy string " + i + "." + j); + } + map.put(key, list); + } + // thread safe, will only be one + liveData = map; + } + + @TearDown(Level.Iteration) + public void teardownLiveData() { + liveData = null; + } + + @Benchmark + public int testParse() throws Exception { + int intDummy = 0; + byte[] bytes = getFileBytesFromResource(doc); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + XMLInputFactory factory = XMLInputFactory.newInstance(); + + XMLStreamReader parser = factory.createXMLStreamReader(bais); + int acc; + do { + acc = parser.next(); + intDummy += acc; + } while (acc != XMLStreamConstants.END_DOCUMENT); + return intDummy; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring the gain of removing array bound checks in various cases + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayBoundCheckRemoval { + + private int[] a; + private int j, u, v; + + @Setup + public void setup() { + a = new int[200]; + } + + @Benchmark + public int[] testForLoopAccess() throws Exception { + int[] a = this.a; + for (int i = 0; i < a.length; i++) { + a[i] = i; + } + return a; + } + + @Benchmark + public int[] testBubblesortStripped() throws Exception { + int[] a = this.a; + int limit = a.length; + int st = -1; + + while (st < limit) { + st++; + limit--; + for (j = st; j < limit; j++) { + u = a[j]; + v = a[j + 1]; + } + } + return a; + } + + @Benchmark + public int[] testBubblesort() throws Exception { + int[] a = this.a; + int j1; + int limit = a.length; + int st = -1; + while (st < limit) { + boolean flipped = false; + st++; + limit--; + for (j1 = st; j1 < limit; j1++) { + if (a[j1] > a[j1 + 1]) { + int T = a[j1]; + a[j1] = a[j1 + 1]; + a[j1 + 1] = T; + flipped = true; + } + } + if (!flipped) { + return a; + } + flipped = false; + for (j1 = limit; --j1 >= st; ) { + if (a[j1] > a[j1 + 1]) { + int T = a[j1]; + a[j1] = a[j1 + 1]; + a[j1 + 1] = T; + flipped = true; + } + } + if (!flipped) { + return a; + } + } + return a; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayClear.java b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayClear.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayClear.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayClear { + + @Param("100000") + private int arraySize; + + private int[] sourceIntArray; + + @Setup + public void setupSubclass() { + sourceIntArray = new int[arraySize]; + for (int i = 0; i < arraySize; i += 1) { + sourceIntArray[i] = i; + } + } + + @Benchmark + public int[] testArrayClear() throws Exception { + int[] intArray = new int[arraySize]; + System.arraycopy(sourceIntArray, 0, intArray, 0, arraySize); + return intArray; + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Stack; +import java.util.Vector; +import java.util.concurrent.TimeUnit; + +/** + * Benchmarking measuring ArrayStoreCheck-performance plus the ability of the optimizer to remove storechecks + * altogether. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@SuppressWarnings("rawtypes") +@State(Scope.Thread) +public class ArrayStoreCheck { + + /** How large should the test-arrays be. */ + public static final int TESTSIZE = 1000; + + private Vector[] fromVectorArr, toVectorArr; + + private Object[] fromObjectArr, toObjectArr; + + private Object[] fromObject2Arr, toObject2Arr; + + private Object[] fromObject3Arr, toObject3Arr; + + private Object[] fromObject4Arr, toObject4Arr; + + @Setup(Level.Iteration) + public void createArrays() { + fromVectorArr = new Vector[TESTSIZE]; + toVectorArr = new Vector[TESTSIZE]; + + fromObjectArr = fromVectorArr; + toObjectArr = toVectorArr; + + /* set every almost 90% of all indices to an object. */ + for (int i = 0; i < TESTSIZE; i++) { + fromVectorArr[i] = new Vector(); + } + for (int i = 0; i < TESTSIZE; i += 10) { + fromVectorArr[i] = null; + } + + fromObject2Arr = new Vector[TESTSIZE][1][][][]; + toObject2Arr = new Vector[TESTSIZE][1][][][]; + + fromObject3Arr = new Stack[TESTSIZE][1][][][]; + toObject3Arr = new Vector[TESTSIZE][1][][][]; + + fromObject4Arr = new Object[TESTSIZE]; + toObject4Arr = new Comparable[TESTSIZE]; + /* set every two indices to an object. */ + for (int i = 0; i < TESTSIZE; i += 2) { + fromObject4Arr[i] = new String("apa?"); + } + } + + /** + * Test that loads from an Vector[] and stores in another Vector[]. The local types of the arrays are both Vector[]. + * Hopefully we only will do a runtime check that we are storing in an exact Vector[]. + */ + @Benchmark + public void testArrayStoreCheckRT1() throws Exception { + Vector[] localFromArray = fromVectorArr; + Vector[] localToArray = toVectorArr; + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localFromArray[i]; + } + } + + /** + * Test that stores a newly created Vector in a Vector[]. The local type of the array is Vector[]. Hopefully we only + * will do a runtime check that we are storing in the same Vector[]. + */ + @Benchmark + public void testArrayStoreCheckRT2() throws Exception { + Vector[] localToArray = toVectorArr; + Vector localVector = new Vector(); + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localVector; + } + } + + /** + * Test that loads from a Vector[] and stores in the same Vector[]. Hopefully we only will remove the storecheck + * altogether due to the fact that the arrays are the same (and easily proven that they are they same). + */ + @Benchmark + public void testArrayStoreCheckRemove1() throws Exception { + Vector[] localToArray = toVectorArr; + for (int i = 2; i < TESTSIZE; i++) { + localToArray[i] = localToArray[i - 2]; + } + } + + /** + * Test that loads from a Vector[] and stores in another Vector[]. The local types of the arrays are both Object[]. + * This should be a tricky case where we statically have no clue what type the arrays actually are of. We should have + * to do a complex check. + */ + @Benchmark + public void testArrayStoreCheckComplex1() throws Exception { + Object[] localFromArray = fromObjectArr; + Object[] localToArray = toObjectArr; + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localFromArray[i]; + } + } + + /** + * Test that loads from a Vector[][][][] and stores in another Vector[][][][]. The local types of the arrays are both + * Object[]. This should be a tricky case where we statically have no clue what type the arrays actually are of. We + * should have to do a complex check. Difference from complex1-test is that the actual types of the arrays are + * multi-dimensioned. + */ + @Benchmark + public void testArrayStoreCheckComplex2() throws Exception { + Object[] localFromArray = fromObject2Arr; + Object[] localToArray = toObject2Arr; + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localFromArray[i]; + } + } + + /** + * Test that loads from a Stack[][][][] and stores in a Vector[][][][]. The local types of the arrays are both + * Object[]. This should be a tricky case where we statically have no clue what type the arrays actually are of. We + * should have to do a complex check. Difference from complex2-test is that the actual types of the from-array is + * different from the actual type of the to-array. + */ + @Benchmark + public void testArrayStoreCheckComplex3() throws Exception { + Object[] localFromArray = fromObject3Arr; + Object[] localToArray = toObject3Arr; + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localFromArray[i]; + } + } + + /** + * Test that loads from a Object[] and stores in a Comparable[]. The local types of the arrays are both Object[]. This + * should be a tricky case where we statically have no clue what type the arrays actually are of. We should have to do + * a complex check. The interesting part with this test is that the destination array is an interface array. + */ + @Benchmark + public void testArrayStoreCheckComplex4() throws Exception { + Object[] localFromArray = fromObject4Arr; + Object[] localToArray = toObject4Arr; + + for (int i = 0; i < TESTSIZE; i++) { + localToArray[i] = localFromArray[i]; + } + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/CopyLoop.java b/test/micro/classes/org/openjdk/bench/vm/compiler/CopyLoop.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/CopyLoop.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring effect of loop optimizations. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class CopyLoop { + + private MyString s; + private Buf b; + + @Setup + public void setup() { + s = new MyString("foobarba"); + b = new Buf(); + } + + /** + * Basic implementation, as a Java programmer would write it. + */ + @Benchmark + public void testCharAtLoop() throws Exception { + for (int i = 0; i < s.length(); i++) { + int c = s.charAt(i); + b.byteBuf[i] = (byte) c; + } + } + + /** Inline charAt and remove the redundant bounds checks. */ + @Benchmark + public void testInlineCharAtLoop() throws Exception { + for (int i = 0; i < s.count; i++) { + int c = s.value[i + s.offset]; + b.byteBuf[i] = (byte) c; + } + } + + /** + * Unroll the loop (I cheat here because I know that the String will always be an even length, real implementation + * would require a pre-loop). + */ + @Benchmark + public void testInlineAndUnrollCharAtLoop() throws Exception { + int startI = 0; + if ((s.count & 0xFFFE) != s.count) { + int c = s.value[s.offset]; + b.byteBuf[0] = (byte) c; + startI = 1; + } + for (int i = startI; i < s.count - 1; i += 2) { + int c = s.value[i + s.offset]; + int d = s.value[i + s.offset + 1]; + b.byteBuf[i] = (byte) c; + b.byteBuf[i + 1] = (byte) d; + } + } + + /** Hoist computation of constants outside of the loop. */ + @Benchmark + public void testInlineAndUnrollAndHoistCharAtLoop() throws Exception { + byte[] byteBuf = b.byteBuf; + if (byteBuf == null) { + throw new NullPointerException(); + } + char[] value = s.value; + int offset = s.offset; + + int startI = offset; + + if ((s.count & 0xFFFE) != s.count) { + int c = value[offset]; + byteBuf[0] = (byte) c; + startI++; + } + + int maxI = s.count + offset - 1; + for (int i = startI; i < maxI; i += 2) { + int c = value[i]; + int d = value[i + 1]; + byteBuf[i] = (byte) c; + byteBuf[i + 1] = (byte) d; + } + } + + private static class Buf { + private byte[] byteBuf = new byte[100]; + } + + public static final class MyString { + private char value[]; + + private int offset; + + private int count; + + public MyString(String original) { + value = original.toCharArray(); + offset = 0; + count = value.length; + } + + public int length() { + return count; + } + + public char charAt(int index) { + if ((index < 0) || (index >= count)) { + throw new StringIndexOutOfBoundsException(index); + } + return value[index + offset]; + } + + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/DivRem.java b/test/micro/classes/org/openjdk/bench/vm/compiler/DivRem.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/DivRem.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Tests speed of division and remainder calculations. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class DivRem { + + private static final int ARRAYSIZE = 500; + + /* instance fields for the constant int division tests. */ + public int[] intValues, intValues2; + + /* instance fields for the constant long division tests. */ + public long[] longValues, longValues2; + + /* instance fields for the tests using the testdr-method. */ + public long[] drLongValues1, drLongValues2; + + public long[] drLongValuesAsInts1, drLongValuesAsInts2; + + @Setup + public void setupSubclass() { + Random r = new Random(4711); + + intValues = new int[ARRAYSIZE]; + intValues2 = new int[ARRAYSIZE]; + longValues = new long[ARRAYSIZE]; + longValues2 = new long[ARRAYSIZE]; + + for (int i = 0; i < ARRAYSIZE; i++) { + intValues[i] = r.nextInt(); + if (intValues[i] == 0) { + intValues[i] = 5353; + } + intValues2[i] = r.nextInt(); + + longValues[i] = r.nextLong(); + if (longValues[i] == 0) { + longValues[i] = 5353L; + } + longValues2[i] = r.nextLong(); + } + + /* generate random longs for 32-64 tests */ + + drLongValues1 = new long[ARRAYSIZE]; + drLongValues2 = new long[ARRAYSIZE]; + drLongValuesAsInts1 = new long[ARRAYSIZE]; + drLongValuesAsInts2 = new long[ARRAYSIZE]; + for (int i = 0; i < ARRAYSIZE; i++) { + long l = r.nextLong(); + if (l == 0L) { + l++; + } + drLongValues1[i] = l; + drLongValuesAsInts1[i] = (long) (int) l; + l = r.nextLong(); + if (l == 0L) { + l++; + } + drLongValues2[i] = l; + drLongValuesAsInts2[i] = (long) (int) l; + } + } + + /** + * Tests integer division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to + * a multiplication instead. + */ + @Benchmark + public int testIntDivConstantDivisor() { + int dummy = 0; + for (int i = 0; i < intValues.length; i++) { + dummy += intValues[i] / 49; + } + return dummy; + } + + /** + * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a + * multiplication instead. + */ + @Benchmark + public long testLongDivConstantDivisor() { + long dummy = 0; + for (int i = 0; i < longValues.length; i++) { + dummy += longValues[i] / 49L + longValues[i] / 0x4949494949L; + } + return dummy; + } + + /** + * Tests integer remainder with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to + * two multiplications instead. + */ + @Benchmark + public int testIntRemConstantDivisor() { + int dummy = 0; + for (int i = 0; i < intValues.length; i++) { + dummy += intValues[i] % 49; + } + return dummy; + } + + /** + * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a + * multiplication instead. + */ + @Benchmark + public long testLongRemConstantDivisor() { + long dummy = 0; + for (int i = 0; i < longValues.length; i++) { + dummy += longValues[i] % 49L + longValues[i] % 0x4949494949L; + } + return dummy; + } + + /** + * Tests integer division with a variable divisor. This benchmark is mainly here to be a comparison against the + * benchmark that performs both divisions and remainder calculations. + */ + @Benchmark + public int testIntDivVariableDivisor() { + int dummy = 0; + for (int i = 0; i < intValues.length; i++) { + dummy += intValues2[i] / intValues[i]; + } + return dummy; + } + + /** + * Tests integer division and remainder with a variable divisor. Both calculations are performed with the same + * divisor, so a JVM should not have to perform two complex calculations. Either a division followed by a + * multiplication, or on X86 using idiv, where the reminder is also returned from the idiv instruction. + */ + @Benchmark + public int testIntDivRemVariableDivisor() { + int dummy = 0; + for (int i = 0; i < intValues.length; i++) { + dummy += intValues2[i] / intValues[i]; + dummy += intValues2[i] % intValues[i]; + } + return dummy; + } + + @Benchmark + public long test64DivRem64() { + long dummy = 0; + for (int i = 0; i < drLongValues1.length; i++) { + long l1 = drLongValues1[i]; + long l2 = drLongValues2[i]; + dummy += l1 / l2; + dummy += l1 % l2; + } + return dummy; + } + + @Benchmark + public long test32DivRem32() { + long dummy = 0; + for (int i = 0; i < drLongValuesAsInts1.length; i++) { + long l1 = drLongValuesAsInts1[i]; + long l2 = drLongValuesAsInts2[i]; + dummy += l1 / l2; + dummy += l1 % l2; + } + return dummy; + } + + @Benchmark + public long test64DivRem32() { + long dummy = 0; + for (int i = 0; i < drLongValues1.length; i++) { + long l1 = drLongValues1[i]; + long l2 = drLongValuesAsInts2[i]; + dummy += l1 / l2; + dummy += l1 % l2; + } + return dummy; + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/Explosion.java b/test/micro/classes/org/openjdk/bench/vm/compiler/Explosion.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/Explosion.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.concurrent.TimeUnit; + +/** + * Tests that the JVM performs object explosion (or some sort of stack allocation). + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Explosion { + + @Param("5") + private int len; + + @Benchmark + public void testHashtableExplosion(Blackhole bh) throws Exception { + Object o = new Object(); + Object[] oa = new Object[len]; + for (int i = 0; i < len; i++) { + oa[i] = new Object(); + } + + Hashtable h = new Hashtable<>(); + + for (int i = 0; i < len; i++) { + h.put(oa[i], o); + } + + Enumeration e = h.elements(); + while (e.hasMoreElements()) { + bh.consume(e.nextElement()); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/InnerClassNullRef.java b/test/micro/classes/org/openjdk/bench/vm/compiler/InnerClassNullRef.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/InnerClassNullRef.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class InnerClassNullRef { + + class Pickles { + int count; + + public Pickles(int x) { + count = x; + } + + public int getCount() { + return count; + } + + public void setCount(int x) { + count = x; + } + } + + class BurgerStand { + public void makeBurgers() { + if (pickles != null) { + // add a pickle + pickles.setCount(pickles.getCount() - 1); + } + } + } + + class BurgerStandNull { + public void makeBurgers() { + if (picklesNull != null) { + // add a pickle + picklesNull.setCount(picklesNull.getCount() - 1); + } + } + } + + private BurgerStand bs; + private BurgerStandNull bsNull; + private Pickles pickles; + private Pickles picklesNull; + + @Setup + public void setup() { + bs = new BurgerStand(); + bsNull = new BurgerStandNull(); + pickles = new Pickles(42); + } + + @Benchmark + public void refIsNull() { + bsNull.makeBurgers(); + } + + @Benchmark + public void refIsNotNull() { + bs.makeBurgers(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/InterfaceCalls.java b/test/micro/classes/org/openjdk/bench/vm/compiler/InterfaceCalls.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/InterfaceCalls.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class InterfaceCalls { + + interface AnInterface { + public int getInt(); + } + + interface SecondInterface { + public int get1(); + } + + interface OnlyHasOneImplInterface { + public int getLong(); + } + + interface AloneInterface { + public int getNumber(); + } + + class SingleImplementor implements OnlyHasOneImplInterface { + public int getLong() { + return 1; + } + } + + class Extender1 extends SingleImplementor { + } + + class FirstClass implements AnInterface { + public int getInt() { + return 1; + } + } + + class SecondClass implements AnInterface { + public int getInt() { + return 2; + } + } + + class ThirdClass implements AnInterface { + public int getInt() { + return -3; + } + } + + class FourthClass implements AnInterface { + public int getInt() { + return -4; + } + } + + class FifthClass implements AnInterface { + public int getInt() { + return -5; + } + } + + class MultiClass1 implements AnInterface, SecondInterface { + public int get1() { + return 1; + } + + public int getInt() { + return 2; + } + } + + class MultiClass2 implements AnInterface, SecondInterface { + public int get1() { + return -1; + } + + public int getInt() { + return -2; + } + } + + class Aloner implements AloneInterface { + public int getNumber() { + return 7; + } + } + + public Object dummy1; + + public Object dummy2; + + public Object dummy3; + + public AnInterface multi1a, multi2a; + + public SecondInterface multi1b, multi2b; + + public Object multic, multic2; + + public AnInterface[] as = new AnInterface[5]; + + public AnInterface multi; + + public OnlyHasOneImplInterface single1; + + public OnlyHasOneImplInterface single2; + + public AloneInterface alone; + + int count; + + @Setup + public void setupSubclass() { + dummy1 = new FirstClass(); + dummy2 = new SecondClass(); + dummy3 = new ThirdClass(); + as[0] = new FirstClass(); + as[1] = new SecondClass(); + as[2] = new ThirdClass(); + as[3] = new FourthClass(); + as[4] = new FifthClass(); + MultiClass1 mc1 = new MultiClass1(); + multi1a = mc1; + multi1b = mc1; + multic = mc1; + MultiClass2 mc2 = new MultiClass2(); + multi2a = mc2; + multi2b = mc2; + multic2 = mc2; + single1 = new SingleImplementor(); + single2 = new Extender1(); + alone = new Aloner(); + } + + private void swapMultiParts() { + AnInterface tmpa = multi1a; + SecondInterface tmpb = multi1b; + multi1a = multi2a; + multi2a = tmpa; + multi1b = multi2b; + multi2b = tmpb; + } + + @SuppressWarnings("unused") + private void swapMulti() { + Object tmp = multic; + multic = multic2; + multic2 = tmp; + } + + /** + * Tests a call where there are multiple implementors but only one of the implementors is every used here so the + * call-site is monomorphic + */ + @Benchmark + public int testMonomorphic() { + return as[0].getInt(); + } + + /** Tests a interface call that only has one single implementation */ + @Benchmark + public int testSingle() { + return alone.getNumber(); + } + + /** + * Tests a call where there is a single implementation but multiple classes that inherit that implementation and both + * these implementors are used. + */ + @Benchmark + public int testSingle2() { + OnlyHasOneImplInterface oi; + if ((count & 1) == 0) { + oi = single1; + } else { + oi = single2; + } + count++; + return oi.getLong(); + } + + /** + * Tests calling two different interface methods in two different interfaces on the same receiver. Make sure to switch + * between two different types of receivers to achieve polymorhpism + */ + @Benchmark + public void testCall2Poly2(Blackhole bh) { + bh.consume(multi1a.getInt()); + bh.consume(multi1b.get1()); + swapMultiParts(); + } + + @Benchmark + public int testCallMulti1Poly2NoSwap() { + return multi1a.getInt(); + } + + /** + * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different + * interfaces take different amounts of time (They do for hotspot) + */ + @Benchmark + public int testCallMulti1Poly2() { + swapMultiParts(); + return multi1a.getInt(); + } + + /** + * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different + * interfaces take different amounts of time (They do for hotspot) + */ + @Benchmark + public int testCallMulti2Poly2() { + swapMultiParts(); + return multi1b.get1(); + } + + /** Interface call with three different receivers */ + @Benchmark + public void testCallPoly3(Blackhole bh) { + for (int kk = 0; kk < 3; kk++) { + bh.consume(as[kk].getInt()); + } + } + + /** Interface call with five different receivers. */ + @Benchmark + public void testCallPoly5(Blackhole bh) { + for (int kk = 0; kk < 3; kk++) { + bh.consume(as[kk].getInt()); + } + } + + int l; + + /** + * Interface call address computation within loop but the receiver preexists the loop and the ac can be moved outside + * of the loop + */ + @Benchmark + public int testAC1() { + AnInterface ai = as[l]; + l = 1 - l; + return ai.getInt(); + } + + /** Tests an interface cast followed by an interface call. */ + @Benchmark + public int testInterfaceCastAndCall() throws Exception { + return ((AnInterface) dummy1).getInt() + ((AnInterface) dummy2).getInt() + + ((AnInterface) dummy3).getInt(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/Multiplication.java b/test/micro/classes/org/openjdk/bench/vm/compiler/Multiplication.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/Multiplication.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Tests speed of multiplication calculations with constants. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Multiplication { + + @Param("500") + private int arraySize; + + private long[] longArraySmall, longArrayBig; + + @Setup + public void setupSubclass() { + longArraySmall = new long[arraySize]; + longArrayBig = new long[arraySize]; + + /* + * small values always have higher 32 bits cleared. big values always + * have higher 32 bits set. + */ + for (int i = 0; i < arraySize; i++) { + longArraySmall[i] = 100L * i + i; + longArrayBig[i] = ((100L * i + i) << 32) + 4543 + i * 4; + } + } + + /* helper for small constant benchmarks. */ + private static long smallConstantHelper(long[] values) { + long sum = 0; + for (long value : values) { + sum += value * 453543L; + } + return sum; + } + + /* helper for big constant benchmarks. */ + private static long bigConstantHelper(long[] values) { + long sum = 0; + for (long value : values) { + sum += value * 4554345533543L; + } + return sum; + } + + /** + * Test multiplications of longs. One of the operands is a small constant and the other is a variable that always is + * small. + */ + @Benchmark + public long testLongSmallVariableSmallConstantMul() { + return smallConstantHelper(longArraySmall); + } + + /** + * Test multiplications of longs. One of the operands is a big constant and the other is a variable that always is + * small. + */ + @Benchmark + public long testLongSmallVariableBigConstantMul() { + return bigConstantHelper(longArraySmall); + } + + /** + * Test multiplications of longs. One of the operands is a small constant and the other is a variable that always is + * big. + */ + @Benchmark + public long testLongBigVariableSmallConstantMul() { + return smallConstantHelper(longArrayBig); + } + + /** + * Test multiplications of longs. One of the operands is a big constant and the other is a variable that always is + * big. + */ + @Benchmark + public long testLongBigVariableBigConstantMul() { + return bigConstantHelper(longArrayBig); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/PostAllocationStores.java b/test/micro/classes/org/openjdk/bench/vm/compiler/PostAllocationStores.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/PostAllocationStores.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +/** + * Tests how well the JVM can remove stores after allocation of objects. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class PostAllocationStores { + + /** Tests allocation with explicit stores of null/zero to all fields. */ + @Benchmark + public Object testAllocationWithNullStores() throws Exception { + return new TestWithNullStores(); + } + + /** + * Tests allocation with explicit stores of non-null/non-zero to all fields. This test exists as a complement to the + * one above. + */ + @Benchmark + public Object testAllocationWithNonNullStores() throws Exception { + return new TestWithNonNullStores(); + } + + /** Tests allocation with explicit stores of null/zero to all fields, where all fields are volatile. */ + @Benchmark + public Object testAllocationWithNullVolatileStores() throws Exception { + return new TestWithNullVolatileStores(); + } + + /** Tests allocation without any explicit stores to any fields. */ + @Benchmark + public Object testAllocationWithoutStores() throws Exception { + return new TestWithoutStores(); + } + + static class TestWithNullStores { + Object objectField1; + Object objectField2; + Object objectField3; + int intField1; + int intField2; + long longField1; + + public TestWithNullStores() { + objectField1 = null; + objectField2 = null; + objectField3 = null; + intField1 = 0; + intField2 = 0; + longField1 = 0L; + } + } + + static class TestWithNonNullStores { + Object objectField1; + Object objectField2; + Object objectField3; + int intField1; + int intField2; + long longField1; + + public TestWithNonNullStores() { + objectField1 = this; + objectField2 = this; + objectField3 = this; + intField1 = 4; + intField2 = 7; + longField1 = 2L; + } + } + + static class TestWithNullVolatileStores { + volatile Object objectField1; + volatile Object objectField2; + volatile Object objectField3; + volatile int intField1; + volatile int intField2; + volatile long longField1; + + public TestWithNullVolatileStores() { + objectField1 = null; + objectField2 = null; + objectField3 = null; + intField1 = 0; + intField2 = 0; + longField1 = 0L; + } + } + + static class TestWithoutStores { + Object objectField1; + Object objectField2; + Object objectField3; + int intField1; + int intField2; + long longField1; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/SpillCode.java b/test/micro/classes/org/openjdk/bench/vm/compiler/SpillCode.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/SpillCode.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Test spill code generation. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class SpillCode { + + @Param("10") + private int iterations; + + private int dummy; + + private int doSomeCalcsInLargeBlockWithInts(int start, int iter) { + + int a1, a2, a3, a4; + int b1, b2, b3, b4; + int c1, c2, c3, c4; + int d1, d2, d3, d4; + int e1, e2, e3, e4; + int f1, f2, f3, f4; + int g1, g2, g3, g4; + int h1, h2, h3, h4; + + // a1 = b1 = c1 = d1 = e1 = f1 = g1 = h1 = (start % 2); + a2 = b2 = c2 = d2 = e2 = f2 = g2 = h2 = (start % 2); + a3 = b3 = c3 = d3 = e3 = f3 = g3 = h3 = (start % 4); + a4 = b4 = c4 = d4 = e4 = f4 = g4 = h4 = (start % 8); + + for (int i = 0; i < iter; i++) { + + // for each section, only x1 needs to survive. + + // a1 = a2 = a3 = a4 = (start + a1) % 2; + a1 = start; + a1 = a1 + a2 + a3 + a4; + a2 = a1 + a2 + a3 + a4; + a3 = a1 + a2 + a3 + a4; + a4 = a1 + a2 + a3 + a4; + a1 = a1 + a2 + a3 + a4; + a2 = a1 + a2 + a3 + a4; + a3 = a1 + a2 + a3 + a4; + a4 = a1 + a2 + a3 + a4; + a1 = a1 + a2 + a3 + a4; + a2 = a1 + a2 + a3 + a4; + a3 = a1 + a2 + a3 + a4; + a4 = a1 + a2 + a3 + a4; + + // b1 = b2 = b3 = b4 = (a4 + b1) % 2; + b1 = a4; + b1 = b1 + b2 + b3 + b4; + b2 = b1 + b2 + b3 + b4; + b3 = b1 + b2 + b3 + b4; + b4 = b1 + b2 + b3 + b4; + b1 = b1 + b2 + b3 + b4; + b2 = b1 + b2 + b3 + b4; + b3 = b1 + b2 + b3 + b4; + b4 = b1 + b2 + b3 + b4; + b1 = b1 + b2 + b3 + b4; + b2 = b1 + b2 + b3 + b4; + b3 = b1 + b2 + b3 + b4; + b4 = b1 + b2 + b3 + b4; + + // c1 = c2 = c3 = c4 = (b4 + c1) % 2; + c1 = b4; + c1 = c1 + c2 + c3 + c4; + c2 = c1 + c2 + c3 + c4; + c3 = c1 + c2 + c3 + c4; + c4 = c1 + c2 + c3 + c4; + c1 = c1 + c2 + c3 + c4; + c2 = c1 + c2 + c3 + c4; + c3 = c1 + c2 + c3 + c4; + c4 = c1 + c2 + c3 + c4; + c1 = c1 + c2 + c3 + c4; + c2 = c1 + c2 + c3 + c4; + c3 = c1 + c2 + c3 + c4; + c4 = c1 + c2 + c3 + c4; + + // d1 = d2 = d3 = d4 = (c4 + d1) % 2; + d1 = c4; + d1 = d1 + d2 + d3 + d4; + d2 = d1 + d2 + d3 + d4; + d3 = d1 + d2 + d3 + d4; + d4 = d1 + d2 + d3 + d4; + d1 = d1 + d2 + d3 + d4; + d2 = d1 + d2 + d3 + d4; + d3 = d1 + d2 + d3 + d4; + d4 = d1 + d2 + d3 + d4; + d1 = d1 + d2 + d3 + d4; + d2 = d1 + d2 + d3 + d4; + d3 = d1 + d2 + d3 + d4; + d4 = d1 + d2 + d3 + d4; + + // e1 = e2 = e3 = e4 = (d4 + e1) % 2; + e1 = d4; + e1 = e1 + e2 + e3 + e4; + e2 = e1 + e2 + e3 + e4; + e3 = e1 + e2 + e3 + e4; + e4 = e1 + e2 + e3 + e4; + e1 = e1 + e2 + e3 + e4; + e2 = e1 + e2 + e3 + e4; + e3 = e1 + e2 + e3 + e4; + e4 = e1 + e2 + e3 + e4; + e1 = e1 + e2 + e3 + e4; + e2 = e1 + e2 + e3 + e4; + e3 = e1 + e2 + e3 + e4; + e4 = e1 + e2 + e3 + e4; + + // f1 = f2 = f3 = f4 = (e4 + f1) % 2; + f1 = e4; + f1 = f1 + f2 + f3 + f4; + f2 = f1 + f2 + f3 + f4; + f3 = f1 + f2 + f3 + f4; + f4 = f1 + f2 + f3 + f4; + f1 = f1 + f2 + f3 + f4; + f2 = f1 + f2 + f3 + f4; + f3 = f1 + f2 + f3 + f4; + f4 = f1 + f2 + f3 + f4; + f1 = f1 + f2 + f3 + f4; + f2 = f1 + f2 + f3 + f4; + f3 = f1 + f2 + f3 + f4; + f4 = f1 + f2 + f3 + f4; + + // g1 = g2 = g3 = g4 = (f4 + g1) % 2; + g1 = f4; + g1 = g1 + g2 + g3 + g4; + g2 = g1 + g2 + g3 + g4; + g3 = g1 + g2 + g3 + g4; + g4 = g1 + g2 + g3 + g4; + g1 = g1 + g2 + g3 + g4; + g2 = g1 + g2 + g3 + g4; + g3 = g1 + g2 + g3 + g4; + g4 = g1 + g2 + g3 + g4; + g1 = g1 + g2 + g3 + g4; + g2 = g1 + g2 + g3 + g4; + g3 = g1 + g2 + g3 + g4; + g4 = g1 + g2 + g3 + g4; + + // h1 = h2 = h3 = h4 = (g4 + h1) % 2; + h1 = g4; + h1 = h1 + h2 + h3 + h4; + h2 = h1 + h2 + h3 + h4; + h3 = h1 + h2 + h3 + h4; + h4 = h1 + h2 + h3 + h4; + h1 = h1 + h2 + h3 + h4; + h2 = h1 + h2 + h3 + h4; + h3 = h1 + h2 + h3 + h4; + h4 = h1 + h2 + h3 + h4; + h1 = h1 + h2 + h3 + h4; + h2 = h1 + h2 + h3 + h4; + h3 = h1 + h2 + h3 + h4; + h4 = h1 + h2 + h3 + h4; + + start = h4; + } + + return start; + } + + /** + * The test runs a loop with many local variables. The issue it reproduces is that if handled wrong, too many variables + * are put on and referenced on stack. The number of iterations is taken from global variable, to prevent static loop + * unrolling. Many of the variables used in the larger loop are local inside the block and do dnot need to survive from + * one iteration to the next. + */ + @Benchmark + public int testSpillForManyInts() throws Exception { + return doSomeCalcsInLargeBlockWithInts(dummy, iterations); + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/StoreAfterStore.java b/test/micro/classes/org/openjdk/bench/vm/compiler/StoreAfterStore.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/StoreAfterStore.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * Tests for removal of redundant stores. It's crucial for the tests to be valid that inlining and allocation is + * performed as described in this file. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class StoreAfterStore { + public int s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5, s6 = 6, s7 = 7, s8 = 8; + + /** + * Test removal of redundant zero stores following an object allocation. + */ + @Benchmark + public AllocAndZeroStoreHelper testAllocAndZeroStore() throws Exception { + return new AllocAndZeroStoreHelper(s1, s2, s3, s4, s5, s6, s7, s8); + } + + /** + * Test removal of stores followed by stores to the same memory location. + */ + @Benchmark + public StoreAndStoreHelper testStoreAndStore() throws Exception { + return new StoreAndStoreHelper(s1, s2, s3, s4, s5, s6, s7, s8); + } + + + /** + * Helper for alloc followed by zero store testing. + */ + static class AllocAndZeroStoreHelper { + public volatile int vf1, vf2, vf3, vf4, vf5, vf6, vf7, vf8; + + public static int s1, s2, s3, s4, s5, s6, s7, s8; + + private AllocAndZeroStoreHelper() { + this.vf1 = 0; + this.vf2 = 0; + this.vf3 = 0; + this.vf4 = 0; + this.vf5 = 0; + this.vf6 = 0; + this.vf7 = 0; + this.vf8 = 0; + } + + private AllocAndZeroStoreHelper(int l1, int l2, int l3, int l4, int l5, int l6, int l7, int l8) { + this(); // Redundant initialization to zero here + + // dummy stores + s1 = l1; + s2 = l2; + s3 = l3; + s4 = l4; + s5 = l5; + s6 = l6; + s7 = l7; + s8 = l8; + } + + } + + /** + * Helper for store made redundant by subsequent store testing. + */ + static class StoreAndStoreHelper { + public volatile int vf1, vf2, vf3, vf4, vf5, vf6, vf7, vf8; + + private StoreAndStoreHelper() { + this.vf1 = -1; + this.vf2 = -1; + this.vf3 = -1; + this.vf4 = -1; + this.vf5 = -1; + this.vf6 = -1; + this.vf7 = -1; + this.vf8 = -1; + } + + private StoreAndStoreHelper(int l1, int l2, int l3, int l4, int l5, int l6, int l7, int l8) { + this(); // Initialize all to -1 here, redundant wrt to the below stores + + this.vf1 = l1; + this.vf2 = l2; + this.vf3 = l3; + this.vf4 = l4; + this.vf5 = l5; + this.vf6 = l6; + this.vf7 = l7; + this.vf8 = l8; + } + + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/Straighten.java b/test/micro/classes/org/openjdk/bench/vm/compiler/Straighten.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/Straighten.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Various small benchmarks testing how well the optimizer straightens code. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Straighten { + + private int[] intArr; + private long[] longArr; + + @Setup + public void setupSubclass() { + int TEST_SIZE = 300; + + Random r = new Random(453543); + + /* + * initialize arrays with some values between 0 and 7. + */ + intArr = new int[TEST_SIZE]; + for (int i = 0; i < TEST_SIZE; i++) { + intArr[i] = r.nextInt(8); + } + + longArr = new long[TEST_SIZE]; + for (int i = 0; i < TEST_SIZE; i++) { + longArr[i] = (long) r.nextInt(8); + } + + } + + private int innerCandidate1int(int i) { + int j = 0; + + if (i == 5) { + /* we know that i isn't 4 and is less than 7 here. */ + j++; + } + if (i == 4) { + /* we know that i is less than 7 here. */ + j += 2; + } + if (i < 7) { + /* we know that i is less than 7, so it isn't greater than 7. */ + j += 4; + } + if (i > 7) { + j += 8; + } + return j; + } + + /** Tests how well serial constant integer compares are straightened. */ + @Benchmark + public int testStraighten1int() throws Exception { + int dummy = 0; + int[] arr = intArr; + for (int i : arr) { + dummy += innerCandidate1int(i); + } + return dummy; + } + + private long innerCandidate1long(long l) { + long j = 0; + + if (l == 5) { + /* we know that l isn't 4 and is less than 7 here. */ + j++; + } + if (l == 4) { + /* we know that l is less than 7 here. */ + j += 2; + } + if (l < 7) { + /* we know that l is less than 7, so it isn't greater than 7. */ + j += 4; + } + if (l > 7) { + j += 8; + } + return j; + } + + /** Tests how well serial constant long compares are straightened. */ + @Benchmark + public int testStraighten1long() throws Exception { + int dummy = 0; + long[] arr = longArr; + for (long l : arr) { + dummy += innerCandidate1long(l); + } + return dummy; + } + + private int innerCandidate2int(int i) { + int j; + + if (i < 5) { + /* j becomes 3, so it should be straightened to j == 3 case below. */ + j = 3; + } else { + /* j becomes 4, so it should be straightened to j == 4 case below. */ + j = 4; + } + + if (j == 4) { + i += 2; + } + if (j == 3) { + i += 4; + } + return i; + } + + /** Tests how well constant integer definitions are straightened. */ + @Benchmark + public int testStraighten2int() throws Exception { + int[] arr = intArr; + int dummy = 0; + for (int i : arr) { + dummy += innerCandidate2int(i); + } + return dummy; + } + + private long innerCandidate2long(long l) { + long j; + + if (l < 5) { + /* j becomes 3, so it should be straightened to j == 3 case below. */ + j = 3; + } else { + /* j becomes 4, so it should be straightened to j == 4 case below. */ + j = 4; + } + + if (j == 4) { + l += 2; + } + if (j == 3) { + l += 4; + } + return l; + } + + /** Tests how well constant long definitions are straightened. */ + @Benchmark + public int testStraighten2long() throws Exception { + int dummy = 0; + long[] arr = longArr; + for (long l : arr) { + dummy += innerCandidate2long(l); + } + return dummy; + } + + private int innerCandidate3int(int i, int j) { + int k = 0; + + if (i == j) { + k++; + } + if (i != j) { + k += 2; + } + if (i < j) { + k += 4; + } + return k; + } + + /** + * Tests how well variable integer compares are straightened. + */ + @Benchmark + public int testStraighten3int() throws Exception { + int dummy = 0; + int[] arr = intArr; + for (int i = 0; i < arr.length - 1; i++) { + dummy += innerCandidate3int(arr[i], arr[i + 1]); + } + return dummy; + } + + private long innerCandidate3long(long i, long j) { + long k = 0; + + if (i == j) { + k++; + } + if (i != j) { + k += 2; + } + if (i < j) { + k += 4; + } + return k; + } + + /** Tests how well variable long compares are straightened. */ + @Benchmark + public int testStraighten3long() throws Exception { + int dummy = 0; + long[] arr = longArr; + for (int i = 0; i < arr.length - 1; i++) { + dummy += innerCandidate3long(arr[i], arr[i + 1]); + } + return dummy; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/compiler/WriteBarrier.java b/test/micro/classes/org/openjdk/bench/vm/compiler/WriteBarrier.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/compiler/WriteBarrier.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class WriteBarrier { + + // For array references + public static final int NUM_REFERENCES_SMALL = 32; + public static final int NUM_REFERENCES_LARGE = 2048; + + // For array update tests + private Object[] theArraySmall; + private Object[] realReferencesSmall; + private Object[] nullReferencesSmall; + private int[] indicesSmall; + + private Object[] theArrayLarge; + private Object[] realReferencesLarge; + private Object[] nullReferencesLarge; + private int[] indicesLarge; + + // For field update tests + public Referencer head = null; + public Referencer tail = null; + + // For random number generation + private int m_w; + private int m_z; + + // For field references + public class Referencer { + Referencer next = null; + Referencer() { + this.next = null; + } + void append(Referencer r) { + this.next = r; + } + void clear() { + this.next = null; + } + } + + @Setup + public void setup() { + theArraySmall = new Object[NUM_REFERENCES_SMALL]; + realReferencesSmall = new Object[NUM_REFERENCES_SMALL]; + nullReferencesSmall = new Object[NUM_REFERENCES_SMALL]; + indicesSmall = new int[NUM_REFERENCES_SMALL]; + + theArrayLarge = new Object[NUM_REFERENCES_LARGE]; + realReferencesLarge = new Object[NUM_REFERENCES_LARGE]; + nullReferencesLarge = new Object[NUM_REFERENCES_LARGE]; + indicesLarge = new int[NUM_REFERENCES_LARGE]; + + m_w = (int) System.currentTimeMillis(); + Random random = new Random(); + m_z = random.nextInt(10000) + 1; + + for (int i = 0; i < NUM_REFERENCES_SMALL; i++) { + indicesSmall[i] = get_random() % (NUM_REFERENCES_SMALL - 1); + realReferencesSmall[i] = new Object(); + } + + for (int i = 0; i < NUM_REFERENCES_LARGE; i++) { + indicesLarge[i] = get_random() % (NUM_REFERENCES_LARGE - 1); + realReferencesLarge[i] = new Object(); + } + + // Build a small linked structure + this.head = new Referencer(); + this.tail = new Referencer(); + this.head.append(this.tail); + + // This will (hopefully) promote objects to old space + // Run with -XX:+DisableExplicitGC to keep + // objects in young space + System.gc(); + } + + private int get_random() { + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return Math.abs((m_z << 16) + m_w); /* 32-bit result */ + } + + @Benchmark + public void testArrayWriteBarrierFastPathRealSmall() { + for (int i = 0; i < NUM_REFERENCES_SMALL; i++) { + theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = realReferencesSmall[indicesSmall[i]]; + } + } + + @Benchmark + public void testArrayWriteBarrierFastPathNullSmall() { + for (int i = 0; i < NUM_REFERENCES_SMALL; i++) { + theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = nullReferencesSmall[indicesSmall[i]]; + } + } + + @Benchmark + public void testArrayWriteBarrierFastPathRealLarge() { + for (int i = 0; i < NUM_REFERENCES_LARGE; i++) { + theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = realReferencesLarge[indicesLarge[i]]; + } + } + + @Benchmark + public void testArrayWriteBarrierFastPathNullLarge() { + for (int i = 0; i < NUM_REFERENCES_LARGE; i++) { + theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = nullReferencesLarge[indicesLarge[i]]; + } + } + + @Benchmark() + public void testFieldWriteBarrierFastPath() { + // Shuffle everything around + this.tail.append(this.head); + this.head.clear(); + this.head.append(this.tail); + this.tail.clear(); + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/gc/Alloc.java b/test/micro/classes/org/openjdk/bench/vm/gc/Alloc.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/gc/Alloc.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.gc; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Alloc { + + public static final int LENGTH = 400; + public static final int ARR_LEN = 100; + public int largeLen = 100; + public int smalllen = 6; + + @Benchmark + public void testLargeConstArray(Blackhole bh) throws Exception { + int localArrlen = ARR_LEN; + for (int i = 0; i < LENGTH; i++) { + Object[] tmp = new Object[localArrlen]; + bh.consume(tmp); + } + } + + @Benchmark + public void testLargeVariableArray(Blackhole bh) throws Exception { + int localArrlen = largeLen; + for (int i = 0; i < LENGTH; i++) { + Object[] tmp = new Object[localArrlen]; + bh.consume(tmp); + } + } + + @Benchmark + public void testSmallConstArray(Blackhole bh) throws Exception { + int localArrlen = largeLen; + for (int i = 0; i < LENGTH; i++) { + Object[] tmp = new Object[localArrlen]; + bh.consume(tmp); + } + } + + @Benchmark + public void testSmallObject(Blackhole bh) throws Exception { + FortyBytes localDummy = null; + for (int i = 0; i < LENGTH; i++) { + FortyBytes tmp = new FortyBytes(); + tmp.next = localDummy; + localDummy = tmp; + bh.consume(tmp); + } + } + + @Benchmark + public void testSmallVariableArray(Blackhole bh) throws Exception { + int localArrlen = smalllen; + for (int i = 0; i < LENGTH; i++) { + Object[] tmp = new Object[localArrlen]; + bh.consume(tmp); + } + } + + final class FortyBytes { + Object next; + int y, z, k, f, g, e, t; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture0.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.capture; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * evaluates anonymous classes creation (for comparison with lambda) + * + * Naming convention: + * - inner_N - lambda captures N local variables + * - inner_this_N - lambda captures 'this' and N local variables + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class Capture0 { + + /* + * volatile is used in order to avoid constant propagation + * That is why the bench is relevant only on TSO platforms (x86, SPARC). + * ARM & PPC - TBD when necessary. + */ + public volatile int wh0 = 0; + public volatile int wh1 = 1; + public volatile int wh2 = 2; + public volatile int wh3 = 3; + public volatile int wh4 = 4; + public volatile int wh5 = 5; + public volatile int wh6 = 6; + public volatile int wh7 = 7; + + public String fortyTwo = "42"; + + @Benchmark() + public FunctionalInterface0 inner0(){ + return new FunctionalInterface0() { + @Override + public Object foo() { + return "42"; + } + }; + } + + @Benchmark() + public FunctionalInterface0 inner_1(){ + final int l0 = wh0; + return new FunctionalInterface0() { + @Override + public Object foo() { + return "42" + l0; + } + }; + } + + + @Benchmark() + public FunctionalInterface0 inner_2(){ + final int l0 = wh0; + final int l1 = wh1; + return new FunctionalInterface0() { + @Override + public Object foo() { + return "42" + l0 + " " + l1; + } + }; + } + + @Benchmark() + public FunctionalInterface0 inner_4(){ + final int l0 = wh0; + final int l1 = wh1; + final int l2 = wh2; + final int l3 = wh3; + return new FunctionalInterface0() { + @Override + public Object foo() { + return "42" + l0 + " " + l1 + " " + l2 + " " + l3; + } + }; + } + + + @Benchmark() + public FunctionalInterface0 inner_8(){ + final int l0 = wh0; + final int l1 = wh1; + final int l2 = wh2; + final int l3 = wh3; + final int l4 = wh4; + final int l5 = wh5; + final int l6 = wh6; + final int l7 = wh7; + return new FunctionalInterface0() { + @Override + public Object foo() { + return "42" + l0 + " " + l1 + " " + l2 + " " + l3 + + " " + l4 + " " + l5 + " " + l6 + " " + l7; + } + }; + } + + @Benchmark() + public FunctionalInterface0 inner_this_0(){ + return new FunctionalInterface0() { + @Override + public Object foo() { + return fortyTwo; + } + }; + } + + @Benchmark() + public FunctionalInterface0 inner_this_1(){ + final int l0 = wh0; + return new FunctionalInterface0() { + @Override + public Object foo() { + return fortyTwo + l0; + } + }; + } + + + @Benchmark() + public FunctionalInterface0 inner_this_2(){ + final int l0 = wh0; + final int l1 = wh1; + return new FunctionalInterface0() { + @Override + public Object foo() { + return fortyTwo + l0 + " " + l1; + } + }; + } + + @Benchmark() + public FunctionalInterface0 inner_this_4(){ + final int l0 = wh0; + final int l1 = wh1; + final int l2 = wh2; + final int l3 = wh3; + return new FunctionalInterface0() { + @Override + public Object foo() { + return fortyTwo + l0 + " " + l1 + " " + l2 + " " + l3; + } + }; + } + + + @Benchmark() + public FunctionalInterface0 inner_this_8(){ + final int l0 = wh0; + final int l1 = wh1; + final int l2 = wh2; + final int l3 = wh3; + final int l4 = wh4; + final int l5 = wh5; + final int l6 = wh6; + final int l7 = wh7; + return new FunctionalInterface0() { + @Override + public Object foo() { + return fortyTwo + l0 + " " + l1 + " " + l2 + " " + l3 + + " " + l4 + " " + l5 + " " + l6 + " " + l7; + } + }; + } + +//--------------------lambda part + + @Benchmark() + public FunctionalInterface0 lambda_00(){ + return () -> "42"; + } + + @Benchmark() + public FunctionalInterface0 lambda_01(){ + int l0 = wh0; + return () -> "42" + l0; + } + + + @Benchmark() + public FunctionalInterface0 lambda_02(){ + int l0 = wh0; + int l1 = wh1; + return () -> "42" + l0 + " " + l1; + } + + @Benchmark() + public FunctionalInterface0 lambda_04(){ + int l0 = wh0; + int l1 = wh1; + int l2 = wh2; + int l3 = wh3; + return () -> "42" + l0 + " " + l1 + " " + l2 + " " + l3; + } + + + @Benchmark() + public FunctionalInterface0 lambda_08(){ + int l0 = wh0; + int l1 = wh1; + int l2 = wh2; + int l3 = wh3; + int l4 = wh4; + int l5 = wh5; + int l6 = wh6; + int l7 = wh7; + return () -> "42" + l0 + " " + l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6 + " " + l7; + } + + @Benchmark() + public FunctionalInterface0 lambda_this_0(){ + return () -> fortyTwo; + } + + @Benchmark() + public FunctionalInterface0 lambda_this_1(){ + int l0 = wh0; + return () -> fortyTwo + l0; + } + + + @Benchmark() + public FunctionalInterface0 lambda_this_2(){ + int l0 = wh0; + int l1 = wh1; + return () -> fortyTwo + l0 + " " + l1; + } + + @Benchmark() + public FunctionalInterface0 lambda_this_4(){ + int l0 = wh0; + int l1 = wh1; + int l2 = wh2; + int l3 = wh3; + return () -> fortyTwo + l0 + " " + l1 + " " + l2 + " " + l3; + } + + + @Benchmark() + public FunctionalInterface0 lambda_this_8(){ + int l0 = wh0; + int l1 = wh1; + int l2 = wh2; + int l3 = wh3; + int l4 = wh4; + int l5 = wh5; + int l6 = wh6; + int l7 = wh7; + return () -> fortyTwo + l0 + " " + l1 + " " + l2 + " " + l3 + + " " + l4 + " " + l5 + " " + l6 + " " + l7; + } + + + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture2.java b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture2.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/Capture2.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.capture; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.Comparator; +import java.util.concurrent.TimeUnit; + +/** + * measure lambda capture + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class Capture2 { + + public static class StaticInner implements Comparator { + @Override + public int compare(Integer x, Integer y) { + return (x < y) ? -1 : ((x > y) ? 1 : 0); + } + } + + public class InstanceInner implements Comparator { + @Override + public int compare(Integer x, Integer y) { + return (x < y) ? -1 : ((x > y) ? 1 : 0); + } + } + + + @Benchmark() + public Comparator anonymous(){ + return new Comparator() { + @Override + public int compare(Integer x, Integer y) { + return (x < y) ? -1 : ((x > y) ? 1 : 0); + } + }; + } + + @Benchmark() + public Comparator inner(){ + return new InstanceInner(); + } + + @Benchmark() + public Comparator inner_static(){ + return new StaticInner(); + } + + @Benchmark() + public Comparator lambda(){ + return (x, y) -> (x < y) ? -1 : ((x > y) ? 1 : 0); + } + + public Comparator mref_static(){ + return Integer::compare; + } + + @Benchmark() + public Comparator mref_unbound(){ + return Integer::compareTo; + } + + @Benchmark() + public Comparator mref_bound(){ + return this::compareInteger; + } + + public int compareInteger(Integer x, Integer y) { + return (x < y) ? -1 : ((x > y) ? 1 : 0); + } + + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/capture/CaptureMR.java b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/CaptureMR.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/CaptureMR.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.capture; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; + +/** + * evaluates method reference capture + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class CaptureMR { + + public static class Mock0 { + public Mock0() { + } + } + + public static Object method_static() { + return "42"; + } + + public Object method_instance() { + return "42"; + } + + @Benchmark() + public FunctionalInterface0 mref_static0(){ + return CaptureMR::method_static; + } + + @Benchmark() + public FunctionalInterface0 mref_bound0(){ + return this::method_instance; + } + + @Benchmark() + public FunctionalInterface0 mref_constructor0(){ + return Mock0::new; + } + + +//--------------------------- + + public static class Mock1 { + private Object oo; + public Mock1(Object o) { + oo = o; + } + } + + public static Object method_static(Object bar) { + return "42" + bar; + } + + public Object method_instance(Object bar) { + return "42" + bar; + } + + @Benchmark() + public FunctionalInterface1 mref_static1(){ + return CaptureMR::method_static; + } + + @Benchmark() + public FunctionalInterface1 mref_bound1(){ + return this::method_instance; + } + + @Benchmark() + public FunctionalInterface1 mref_constructor1(){ + return Mock1::new; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.capture; + +/** + * Functional Interface for lambdas + * FunctionalInterfaceN - where N is number of parameters + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +public interface FunctionalInterface0 { + + public Object foo(); + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.capture; + +/** + * Functional Interface for lambdas + * FunctionalInterfaceN - where N is number of parameters + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +public interface FunctionalInterface1 { + + public Object foo(Object bar); + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainAnonymCap0 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1(); + start2 = get2(); + start4 = get4(); + start8 = get8(); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0() { + return new TopLevel() { + @Override + public String getImage() { + return "GOT: "; + } + }; + } + + public static Level get1() { + return new Level() { + @Override + public Level up() { + return get0(); + } + }; + } + + public static Level get2() { + return new Level() { + @Override + public Level up() { + return get1(); + } + }; + } + + public static Level get3() { + return new Level() { + @Override + public Level up() { + return get2(); + } + }; + } + + public static Level get4() { + return new Level() { + @Override + public Level up() { + return get3(); + } + }; + } + + public static Level get5() { + return new Level() { + @Override + public Level up() { + return get4(); + } + }; + } + + public static Level get6() { + return new Level() { + @Override + public Level up() { + return get5(); + } + }; + } + + public static Level get7() { + return new Level() { + @Override + public Level up() { + return get6(); + } + }; + } + + public static Level get8() { + return new Level() { + @Override + public Level up() { + return get7(); + } + }; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainAnonymCap1 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1("capture me"); + start2 = get2("capture me"); + start4 = get4("capture me"); + start8 = get8("capture me"); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0(String v) { + return new TopLevel() { + @Override + public String getImage() { + return "GOT: "+v; + } + }; + } + + public static Level get1(String v) { + return new Level() { + @Override + public Level up() { + return get0(v); + } + }; + } + + public static Level get2(String v) { + return new Level() { + @Override + public Level up() { + return get1(v); + } + }; + } + + public static Level get3(String v) { + return new Level() { + @Override + public Level up() { + return get2(v); + } + }; + } + + public static Level get4(String v) { + return new Level() { + @Override + public Level up() { + return get3(v); + } + }; + } + + public static Level get5(String v) { + return new Level() { + @Override + public Level up() { + return get4(v); + } + }; + } + + public static Level get6(String v) { + return new Level() { + @Override + public Level up() { + return get5(v); + } + }; + } + + public static Level get7(String v) { + return new Level() { + @Override + public Level up() { + return get6(v); + } + }; + } + + public static Level get8(String v) { + return new Level() { + @Override + public Level up() { + return get7(v); + } + }; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainAnonymCap4 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1("capture me", "and me", "me too", "wait! what about me?"); + start2 = get2("capture me", "and me", "me too", "wait! what about me?"); + start4 = get4("capture me", "and me", "me too", "wait! what about me?"); + start8 = get8("capture me", "and me", "me too", "wait! what about me?"); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0(String v0, String v1, String v2, String v3) { + return new TopLevel() { + @Override + public String getImage() { + return "GOT: " + v0 + "," + v1 + "," + v2 + "," + v3; + } + }; + } + + public static Level get1(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get0(v0, v1, v2, v3); + } + }; + } + + public static Level get2(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get1(v0, v1, v2, v3); + } + }; + } + + public static Level get3(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get2(v0, v1, v2, v3); + } + }; + } + + public static Level get4(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get3(v0, v1, v2, v3); + } + }; + } + + public static Level get5(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get4(v0, v1, v2, v3); + } + }; + } + + public static Level get6(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get5(v0, v1, v2, v3); + } + }; + } + + public static Level get7(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get6(v0, v1, v2, v3); + } + }; + } + + public static Level get8(String v0, String v1, String v2, String v3) { + return new Level() { + @Override + public Level up() { + return get7(v0, v1, v2, v3); + } + }; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainBase.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainBase.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainBase.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; + +import org.openjdk.jmh.infra.Blackhole; + +public class ChainBase { + + protected void process(Blackhole bh, Level start) { + Level curr = start; + while (true) { + curr = curr.up(); + if(curr == null) break; + bh.consume(curr); + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainLambdaCap0 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1(); + start2 = get2(); + start4 = get4(); + start8 = get8(); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0() { + return () -> "GOT: "; + } + + public static Level get1() { + return () -> get0(); + } + + public static Level get2() { + return () -> get1(); + } + + public static Level get3() { + return () -> get2(); + } + + public static Level get4() { + return () -> get3(); + } + + public static Level get5() { + return () -> get4(); + } + + public static Level get6() { + return () -> get5(); + } + + public static Level get7() { + return () -> get6(); + } + + public static Level get8() { + return () -> get7(); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainLambdaCap1 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1("capture me"); + start2 = get2("capture me"); + start4 = get4("capture me"); + start8 = get8("capture me"); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0(String v) { + return () -> "GOT: "+v; + } + + public static Level get1(String v) { + return () -> get0(v); + } + + public static Level get2(String v) { + return () -> get1(v); + } + + public static Level get3(String v) { + return () -> get2(v); + } + + public static Level get4(String v) { + return () -> get3(v); + } + + public static Level get5(String v) { + return () -> get4(v); + } + + public static Level get6(String v) { + return () -> get5(v); + } + + public static Level get7(String v) { + return () -> get6(v); + } + + public static Level get8(String v) { + return () -> get7(v); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainLambdaCap4 extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1("capture me", "and me", "me too", "wait! what about me?"); + start2 = get2("capture me", "and me", "me too", "wait! what about me?"); + start4 = get4("capture me", "and me", "me too", "wait! what about me?"); + start8 = get8("capture me", "and me", "me too", "wait! what about me?"); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0(String v0, String v1, String v2, String v3) { + return () -> "GOT: " + v0 + "," + v1 + "," + v2 + "," + v3; + } + + public static Level get1(String v0, String v1, String v2, String v3) { + return () -> get0(v0, v1, v2, v3); + } + + public static Level get2(String v0, String v1, String v2, String v3) { + return () -> get1(v0, v1, v2, v3); + } + + public static Level get3(String v0, String v1, String v2, String v3) { + return () -> get2(v0, v1, v2, v3); + } + + public static Level get4(String v0, String v1, String v2, String v3) { + return () -> get3(v0, v1, v2, v3); + } + + public static Level get5(String v0, String v1, String v2, String v3) { + return () -> get4(v0, v1, v2, v3); + } + + public static Level get6(String v0, String v1, String v2, String v3) { + return () -> get5(v0, v1, v2, v3); + } + + public static Level get7(String v0, String v1, String v2, String v3) { + return () -> get6(v0, v1, v2, v3); + } + + public static Level get8(String v0, String v1, String v2, String v3) { + return () -> get7(v0, v1, v2, v3); + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainMrefBound extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1(); + start2 = get2(); + start4 = get4(); + start8 = get8(); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public TopLevel get0() { + return () -> "GOT: "; + } + + public Level get1() { + return this::get0; + } + + public Level get2() { + return this::get1; + } + + public Level get3() { + return this::get2; + } + + public Level get4() { + return this::get3; + } + + public Level get5() { + return this::get4; + } + + public Level get6() { + return this::get5; + } + + public Level get7() { + return this::get6; + } + + public Level get8() { + return this::get7; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Chain of (capture + invocation) microbenchmark. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ChainMrefUnbound extends ChainBase { + + public Level start1; + public Level start2; + public Level start4; + public Level start8; + + @Setup + public void init() { + start1 = get1(); + start2 = get2(); + start4 = get4(); + start8 = get8(); + } + + @Benchmark + @OperationsPerInvocation(1) + public void call1(Blackhole bh) { + process(bh, start1); + } + + @Benchmark + @OperationsPerInvocation(2) + public void call2(Blackhole bh) { + process(bh, start2); + } + + @Benchmark + @OperationsPerInvocation(4) + public void call4(Blackhole bh) { + process(bh, start4); + } + + @Benchmark + @OperationsPerInvocation(8) + public void call8(Blackhole bh) { + process(bh, start8); + } + + public static TopLevel get0() { + return () -> "GOT: "; + } + + public static Level get1() { + return ChainMrefUnbound::get0; + } + + public static Level get2() { + return ChainMrefUnbound::get1; + } + + public static Level get3() { + return ChainMrefUnbound::get2; + } + + public static Level get4() { + return ChainMrefUnbound::get3; + } + + public static Level get5() { + return ChainMrefUnbound::get4; + } + + public static Level get6() { + return ChainMrefUnbound::get5; + } + + public static Level get7() { + return ChainMrefUnbound::get6; + } + + public static Level get8() { + return ChainMrefUnbound::get7; + } + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/Level.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/Level.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/Level.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; + +/** + * Functional Interface. + */ +public interface Level { + + public Level up(); + + default String getImage() { + return ""; + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/chain/TopLevel.java b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/TopLevel.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/chain/TopLevel.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.chain; + +/** + * Functional Interface as end of chain marker. + */ +public interface TopLevel extends Level { + + @Override + default Level up() { + return null; + } + + @Override + public String getImage(); + +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannI.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannI.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannI.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; +import java.util.function.IntBinaryOperator; + +/** + * evaluates invocation costs in case of long recursive chains + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class AckermannI { + + // ackermann(1,1748)+ ackermann(2,1897)+ ackermann(3,8); == 9999999 calls + public static final int Y1 = 1748; + public static final int Y2 = 1897; + public static final int Y3 = 8; + + public static int ack(int x, int y) { + return x == 0 ? + y + 1 : + (y == 0 ? + ack(x - 1, 1) : + ack(x - 1, ack(x, y - 1))); + } + + @Benchmark + @OperationsPerInvocation(9999999) + public int func() { + return ack(1, Y1) + ack(2, Y2) + ack(3, Y3); + } + + public static final IntBinaryOperator inner_ack = + new IntBinaryOperator() { + @Override + public int applyAsInt(int x, int y) { + return x == 0 ? + y + 1 : + (y == 0 ? + inner_ack.applyAsInt(x - 1, 1) : + inner_ack.applyAsInt(x - 1, inner_ack.applyAsInt(x, y - 1))); + + } + }; + + @Benchmark + @OperationsPerInvocation(9999999) + public int inner() { + return inner_ack.applyAsInt(1, Y1) + inner_ack.applyAsInt(2, Y2) + inner_ack.applyAsInt(3, Y3); + } + + public static final IntBinaryOperator lambda_ack = + (x, y) -> x == 0 ? + y + 1 : + (y == 0 ? + AckermannI.lambda_ack.applyAsInt(x - 1, 1) : + AckermannI.lambda_ack.applyAsInt(x - 1, AckermannI.lambda_ack.applyAsInt(x, y - 1))); + + + @Benchmark + @OperationsPerInvocation(9999999) + public int lambda() { + return lambda_ack.applyAsInt(1, Y1) + lambda_ack.applyAsInt(2, Y2) + lambda_ack.applyAsInt(3, Y3); + } + + public static final IntBinaryOperator mref_ack = AckermannI::mref_ack_helper; + + public static int mref_ack_helper(int x, int y) { + return x == 0 ? + y + 1 : + (y == 0 ? + mref_ack.applyAsInt(x - 1, 1) : + mref_ack.applyAsInt(x - 1, mref_ack.applyAsInt(x, y - 1))); + } + + @Benchmark + @OperationsPerInvocation(9999999) + public int mref() { + return mref_ack.applyAsInt(1, Y1) + mref_ack.applyAsInt(2, Y2) + mref_ack.applyAsInt(3, Y3); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannL.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannL.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/AckermannL.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +import java.util.concurrent.TimeUnit; +import java.util.function.BinaryOperator; + +/** + * evaluates invocation costs in case of long recursive chains + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class AckermannL { + + // ackermann(1,1748)+ ackermann(2,1897)+ ackermann(3,8); == 9999999 calls + public static final int Y1 = 1748; + public static final int Y2 = 1897; + public static final int Y3 = 8; + + public static Integer ack(Integer x, Integer y) { + return x == 0 ? + y + 1 : + (y == 0 ? + ack(x - 1, 1) : + ack(x - 1, ack(x, y - 1))); + } + + @Benchmark + @OperationsPerInvocation(9999999) + public Integer func() { + return ack(1, Y1) + ack(2, Y2) + ack(3, Y3); + } + + public static final BinaryOperator inner_ack = + new BinaryOperator() { + @Override + public Integer apply(Integer x, Integer y) { + return x == 0 ? + y + 1 : + (y == 0 ? + inner_ack.apply(x - 1, 1) : + inner_ack.apply(x - 1, inner_ack.apply(x, y - 1))); + } + }; + + @Benchmark + @OperationsPerInvocation(9999999) + public Integer inner() { + return inner_ack.apply(1, Y1) + inner_ack.apply(2, Y2) + inner_ack.apply(3, Y3); + } + + public static final BinaryOperator lambda_ack = + (x, y) -> x == 0 ? + y + 1 : + (y == 0 ? + AckermannL.lambda_ack.apply(x - 1, 1) : + AckermannL.lambda_ack.apply(x - 1, AckermannL.lambda_ack.apply(x, y - 1))); + + + @Benchmark + @OperationsPerInvocation(9999999) + public Integer lambda() { + return lambda_ack.apply(1, Y1) + lambda_ack.apply(2, Y2) + lambda_ack.apply(3, Y3); + } + + public static final BinaryOperator mref_ack = AckermannL::mref_ack_helper; + + public static Integer mref_ack_helper(Integer x, Integer y) { + return x == 0 ? + y + 1 : + (y == 0 ? + mref_ack.apply(x - 1, 1) : + mref_ack.apply(x - 1, mref_ack.apply(x, y - 1))); + } + + @Benchmark + @OperationsPerInvocation(9999999) + public Integer mref() { + return mref_ack.apply(1, Y1) + mref_ack.apply(2, Y2) + mref_ack.apply(3, Y3); + } + + public static final BinaryOperator mref_ackIII = AckermannL::mref_ack_helperIII; + + public static int mref_ack_helperIII(int x, int y) { + return x == 0 ? + y + 1 : + (y == 0 ? + mref_ackIII.apply(x - 1, 1) : + mref_ackIII.apply(x - 1, mref_ackIII.apply(x, y - 1))); + } + + @Benchmark + @OperationsPerInvocation(9999999) + public Integer mrefIII() { + return mref_ackIII.apply(1, Y1) + mref_ackIII.apply(2, Y2) + mref_ackIII.apply(3, Y3); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function0.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +/** + * evaluates invocation costs. + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Function0 { + + public interface FunctionI { + int foo(); + } + + public interface FunctionL { + Integer foo(); + } + + private static int valueI = 40002; // bypass Integer.cache + private static Integer valueL = Integer.valueOf(valueI); + + public int fooInstanceI() { + return valueI; + } + + public static int fooStaticI() { + return valueI; + } + + public Integer fooInstanceL() { + return valueL; + } + + public static Integer fooStaticL() { + return valueL; + } + + @Benchmark + public int baselineI() { + return fooInstanceI(); + } + + @Benchmark + public Integer baselineL() { + return fooInstanceL(); + } + + public final FunctionI anonymI = + new FunctionI() { + @Override + public int foo() { + return valueI; + } + }; + + public final FunctionL anonymL = + new FunctionL() { + @Override + public Integer foo() { + return valueL; + } + }; + + @Benchmark + public int innerI() { + return anonymI.foo(); + } + + @Benchmark + public Integer innerL() { + return anonymL.foo(); + } + + public final FunctionI lambdaI = () -> valueI; + + public final FunctionL lambdaL = () -> valueL; + + @Benchmark + public int lambdaI() { + return lambdaI.foo(); + } + + @Benchmark + public Integer lambdaL() { + return lambdaL.foo(); + } + + public final FunctionI mref_I2I = Function0::fooStaticI; + public final FunctionI mref_I2I_bound = this::fooInstanceI; + + public final FunctionL mref_I2L = Function0::fooStaticI; + public final FunctionL mref_I2L_bound = this::fooInstanceI; + + public final FunctionI mref_L2I = Function0::fooStaticL; + public final FunctionI mref_L2I_bound = this::fooInstanceL; + + public final FunctionL mref_L2L = Function0::fooStaticL; + public final FunctionL mref_L2L_bound = this::fooInstanceL; + + // mref naming + // sig1_sig2 where: + // sig1 - signature of the method referenced by method ref + // sig2 - FuntionalInterface signature + + @Benchmark + public int mrefI_I() { + return mref_I2I.foo(); + } + + @Benchmark + public int mref_bndI_I() { + return mref_I2I_bound.foo(); + } + + @Benchmark + public Integer mrefI_L() { + return mref_I2L.foo(); + } + + @Benchmark + public Integer mref_bndI_L() { + return mref_I2L_bound.foo(); + } + + @Benchmark + public int mrefL_I() { + return mref_L2I.foo(); + } + + @Benchmark + public int mref_bndL_I() { + return mref_L2I_bound.foo(); + } + + @Benchmark + public Integer mrefL_L() { + return mref_L2L.foo(); + } + + @Benchmark + public Integer mref_bndL_L() { + return mref_L2L_bound.foo(); + } + + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function1.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function1.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Function1.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +/** + * evaluates invocation costs. + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Function1 { + + public interface FunctionII { + int foo(int x); + } + + public interface FunctionIL { + int foo(Integer x); + } + + public interface FunctionLL { + Integer foo(Integer x); + } + + private static final int LIMIT = 1024; + + private final int[] dataI = new int[LIMIT + 1]; + private final Integer[] dataL = new Integer[LIMIT + 1]; + + @Setup(Level.Iteration) + public void setup() { + for (int i = 0; i < dataI.length; i++) { + int value = ThreadLocalRandom.current().nextInt(10001,420000); // bypass Integer.cache + dataI[i] = value; + dataL[i] = value; + } + } + + + + public int fooInstanceII(int x) { + return x; + } + + public static int fooStaticII(int x) { + return x; + } + + public int fooInstanceIL(Integer v) { + return v; + } + + public static int fooStaticIL(Integer v) { + return v; + } + + public Integer fooInstanceLL(Integer v) { + return v; + } + + public static Integer fooStaticLL(Integer v) { + return v; + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void baselineII(Blackhole bh) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(fooInstanceII(dataI[i])); + } + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void baselineIL(Blackhole bh) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(fooInstanceIL(dataL[i])); + } + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void baselineLL(Blackhole bh) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(fooInstanceLL(dataL[i])); + } + } + + public final FunctionII anonymII = + new FunctionII() { + @Override + public int foo(int x) { + return x; + } + }; + + public final FunctionIL anonymIL = + new FunctionIL() { + @Override + public int foo(Integer v) { + return v; + } + }; + + public final FunctionLL anonymLL = + new FunctionLL() { + @Override + public Integer foo(Integer v) { + return v; + } + }; + + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void innerII(Blackhole bh) { + processII(bh, anonymII); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void innerIL(Blackhole bh) { + processIL(bh, anonymIL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void innerLL(Blackhole bh) { + processLL(bh, anonymLL); + } + + public final FunctionII lambdaII = x -> x; + + public final FunctionIL lambdaIL = v -> v; + + public final FunctionLL lambdaLL = v -> v; + + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void lambdaII(Blackhole bh) { + processII(bh, lambdaII); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void lambdaIL(Blackhole bh) { + processIL(bh, lambdaIL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void lambdaLL(Blackhole bh) { + processLL(bh, lambdaLL); + } + + + + public final FunctionII mref_II2II = Function1::fooStaticII; + public final FunctionII mref_II2II_bound = this::fooInstanceII; + public final FunctionIL mref_II2IL = Function1::fooStaticII; + public final FunctionIL mref_II2IL_bound = this::fooInstanceII; + public final FunctionLL mref_II2LL = Function1::fooStaticII; + public final FunctionLL mref_II2LL_bound = this::fooInstanceII; + + public final FunctionII mref_IL2II = Function1::fooStaticIL; + public final FunctionII mref_IL2II_bound = this::fooInstanceIL; + public final FunctionIL mref_IL2IL = Function1::fooStaticIL; + public final FunctionIL mref_IL2IL_bound = this::fooInstanceIL; + public final FunctionLL mref_IL2LL = Function1::fooStaticIL; + public final FunctionLL mref_IL2LL_bound = this::fooInstanceIL; + + public final FunctionII mref_LL2II = Function1::fooStaticLL; + public final FunctionII mref_LL2II_bound = this::fooInstanceLL; + public final FunctionIL mref_LL2IL = Function1::fooStaticLL; + public final FunctionIL mref_LL2IL_bound = this::fooInstanceLL; + public final FunctionLL mref_LL2LL = Function1::fooStaticLL; + public final FunctionLL mref_LL2LL_bound = this::fooInstanceLL; + + + // mref naming + // sig1_sig2 where: + // sig1 - signature of the method referenced by method ref + // sig2 - FuntionalInterface signature + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefII_II(Blackhole bh) { + processII(bh, mref_II2II); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndII_II(Blackhole bh) { + processII(bh, mref_II2II_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefII_IL(Blackhole bh) { + processIL(bh, mref_II2IL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndII_IL(Blackhole bh) { + processIL(bh, mref_II2IL_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefII_LL(Blackhole bh) { + processLL(bh, mref_II2LL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndII_LL(Blackhole bh) { + processLL(bh, mref_II2LL_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefIL_II(Blackhole bh) { + processII(bh, mref_IL2II); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndIL_II(Blackhole bh) { + processII(bh, mref_IL2II_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefIL_IL(Blackhole bh) { + processIL(bh, mref_IL2IL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndIL_IL(Blackhole bh) { + processIL(bh, mref_IL2IL_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefIL_LL(Blackhole bh) { + processLL(bh, mref_IL2LL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndIL_LL(Blackhole bh) { + processLL(bh, mref_IL2LL_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefLL_II(Blackhole bh) { + processII(bh, mref_LL2II); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndLL_II(Blackhole bh) { + processII(bh, mref_LL2II_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefLL_IL(Blackhole bh) { + processIL(bh, mref_LL2IL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndLL_IL(Blackhole bh) { + processIL(bh, mref_LL2IL_bound); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mrefLL_LL(Blackhole bh) { + processLL(bh, mref_LL2LL); + } + + @Benchmark + @OperationsPerInvocation(LIMIT) + public void mref_bndLL_LL(Blackhole bh) { + processLL(bh, mref_LL2LL_bound); + } + + + private void processII(Blackhole bh, FunctionII func) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(func.foo(dataI[i])); + } + } + + private void processIL(Blackhole bh, FunctionIL func) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(func.foo(dataL[i])); + } + } + + private void processLL(Blackhole bh, FunctionLL func) { + for (int i = 0; i < LIMIT; i++) { + bh.consume(func.foo(dataL[i])); + } + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph0.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph0.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph0.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.function.IntUnaryOperator; + +/** + * evaluates N-morphic invocation costs. + * N different lambdas each capture 0 variable + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Morph0 { + + + private static final int LIMIT = 16536; + private static final int OPS = 4; + private static final int OPERATIONS = OPS*LIMIT; + + // _N; where N - how many different targets + private IntUnaryOperator[] inner_1; + private IntUnaryOperator[] inner_2; + private IntUnaryOperator[] inner_4; + + private IntUnaryOperator[] lambda_1; + private IntUnaryOperator[] lambda_2; + private IntUnaryOperator[] lambda_4; + + private IntUnaryOperator[] unbounded_mref_1; + private IntUnaryOperator[] unbounded_mref_2; + private IntUnaryOperator[] unbounded_mref_4; + + private IntUnaryOperator[] bounded_mref_1; + private IntUnaryOperator[] bounded_mref_2; + private IntUnaryOperator[] bounded_mref_4; + + @Setup(Level.Trial) + public void setup() { + setup_inner(); + setup_lambda(); + setup_unbounded_mref(); + setup_bounded_mref(); + } + + private void setup_inner() { + inner_4 = new IntUnaryOperator[] { + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + 1; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + 2; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + 3; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + 4; + } + }, + }; + inner_2 = new IntUnaryOperator[] { inner_4[0], inner_4[1], inner_4[0], inner_4[1], }; + inner_1 = new IntUnaryOperator[] { inner_4[0], inner_4[0], inner_4[0], inner_4[0], }; + } + + private void setup_lambda() { + lambda_4 = new IntUnaryOperator[] { + x -> x + 1, + x -> x + 2, + x -> x + 3, + x -> x + 4, + }; + lambda_2 = new IntUnaryOperator[] { lambda_4[0], lambda_4[1], lambda_4[0], lambda_4[1], }; + lambda_1 = new IntUnaryOperator[] { lambda_4[0], lambda_4[0], lambda_4[0], lambda_4[0], }; + } + + public static int func1(int x) { + return x + 1; + } + + public static int func2(int x) { + return x + 2; + } + + public static int func3(int x) { + return x + 3; + } + + public static int func4(int x) { + return x + 4; + } + + private void setup_unbounded_mref() { + unbounded_mref_4 = new IntUnaryOperator[] { + Morph0::func1, + Morph0::func2, + Morph0::func3, + Morph0::func4, + }; + unbounded_mref_2 = new IntUnaryOperator[] { unbounded_mref_4[0], unbounded_mref_4[1], unbounded_mref_4[0], unbounded_mref_4[1], }; + unbounded_mref_1 = new IntUnaryOperator[] { unbounded_mref_4[0], unbounded_mref_4[0], unbounded_mref_4[0], unbounded_mref_4[0], }; + } + + public int ifunc1(int x) { + return x + 1; + } + + public int ifunc2(int x) { + return x + 2; + } + + public int ifunc3(int x) { + return x + 3; + } + + public int ifunc4(int x) { + return x + 4; + } + + private void setup_bounded_mref() { + bounded_mref_4 = new IntUnaryOperator[] { + this::ifunc1, + this::ifunc2, + this::ifunc3, + this::ifunc4, + }; + bounded_mref_2 = new IntUnaryOperator[] { bounded_mref_4[0], bounded_mref_4[1], bounded_mref_4[0], bounded_mref_4[1], }; + bounded_mref_1 = new IntUnaryOperator[] { bounded_mref_4[0], bounded_mref_4[0], bounded_mref_4[0], bounded_mref_4[0], }; + } + + public void process(Blackhole bh, IntUnaryOperator[] operations) { + for (int i = 0; i < LIMIT; i++) { + for (IntUnaryOperator op : operations) { + bh.consume(op.applyAsInt(i)); + } + } + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner1(Blackhole bh) { + process(bh, inner_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner2(Blackhole bh) { + process(bh, inner_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner4(Blackhole bh) { + process(bh, inner_4); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda1(Blackhole bh) { + process(bh, lambda_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda2(Blackhole bh) { + process(bh, lambda_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda4(Blackhole bh) { + process(bh, lambda_4); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref1(Blackhole bh) { + process(bh, unbounded_mref_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref2(Blackhole bh) { + process(bh, unbounded_mref_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref4(Blackhole bh) { + process(bh, unbounded_mref_4); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref_bnd1(Blackhole bh) { + process(bh, bounded_mref_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref_bnd2(Blackhole bh) { + process(bh, bounded_mref_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void mref_bnd4(Blackhole bh) { + process(bh, bounded_mref_4); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph1.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph1.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph1.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.function.IntUnaryOperator; + +/** + * evaluates N-morphic invocation costs. + * N different lambdas each capture 1 variable + * + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Morph1 { + + + private static final int LIMIT = 16536; + private static final int OPS = 4; + private static final int OPERATIONS = OPS*LIMIT; + + // _N; where N - how many different targets + private IntUnaryOperator[] inner_1; + private IntUnaryOperator[] inner_2; + private IntUnaryOperator[] inner_4; + + private IntUnaryOperator[] lambda_1; + private IntUnaryOperator[] lambda_2; + private IntUnaryOperator[] lambda_4; + + @Setup(Level.Trial) + public void setup() { + setup_inner(1,2,3,4); + setup_lambda(1,2,3,4); + } + + private void setup_inner(int a, int b, int c, int d) { + inner_4 = new IntUnaryOperator[] { + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + a; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + b; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + c; + } + }, + new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + d; + } + }, + }; + inner_2 = new IntUnaryOperator[] { inner_4[0], inner_4[1], inner_4[0], inner_4[1], }; + inner_1 = new IntUnaryOperator[] { inner_4[0], inner_4[0], inner_4[0], inner_4[0], }; + } + + private void setup_lambda(int a, int b, int c, int d) { + lambda_4 = new IntUnaryOperator[] { + x -> x + a, + x -> x + b, + x -> x + c, + x -> x + d, + }; + lambda_2 = new IntUnaryOperator[] { lambda_4[0], lambda_4[1], lambda_4[0], lambda_4[1], }; + lambda_1 = new IntUnaryOperator[] { lambda_4[0], lambda_4[0], lambda_4[0], lambda_4[0], }; + } + + public void process(Blackhole bh, IntUnaryOperator[] operations) { + for (int i = 0; i < LIMIT; i++) { + for (IntUnaryOperator op : operations) { + bh.consume(op.applyAsInt(i)); + } + } + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner1(Blackhole bh) { + process(bh, inner_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner2(Blackhole bh) { + process(bh, inner_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner4(Blackhole bh) { + process(bh, inner_4); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda1(Blackhole bh) { + process(bh, lambda_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda2(Blackhole bh) { + process(bh, lambda_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda4(Blackhole bh) { + process(bh, lambda_4); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph2.java b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph2.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lambda/invoke/Morph2.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lambda.invoke; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.function.IntUnaryOperator; + +/** + * evaluates N-morphic invocation costs. + * the same lambda capture different variables + * @author Sergey Kuksenko (sergey.kuksenko@oracle.com) + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Morph2 { + + + private static final int LIMIT = 16536; + private static final int OPS = 4; + private static final int OPERATIONS = OPS*LIMIT; + + // _N; where N - how many different targets + private IntUnaryOperator[] inner_1; + private IntUnaryOperator[] inner_2; + private IntUnaryOperator[] inner_4; + + private IntUnaryOperator[] lambda_1; + private IntUnaryOperator[] lambda_2; + private IntUnaryOperator[] lambda_4; + + @Setup(Level.Trial) + public void setup() { + setup_inner(1,2,3,4); + setup_lambda(1,2,3,4); + } + + private void setup_inner(int a, int b, int c, int d) { + inner_4 = new IntUnaryOperator[] { + makeInner(a), + makeInner(b), + makeInner(c), + makeInner(d), + }; + inner_2 = new IntUnaryOperator[] { inner_4[0], inner_4[1], inner_4[0], inner_4[1], }; + inner_1 = new IntUnaryOperator[] { inner_4[0], inner_4[0], inner_4[0], inner_4[0], }; + } + + private IntUnaryOperator makeInner(final int a) { + return new IntUnaryOperator() { + @Override + public int applyAsInt(int x) { + return x + a; + } + }; + } + + private void setup_lambda(int a, int b, int c, int d) { + lambda_4 = new IntUnaryOperator[] { + makeLambda(a), + makeLambda(b), + makeLambda(c), + makeLambda(d), + }; + lambda_2 = new IntUnaryOperator[] { lambda_4[0], lambda_4[1], lambda_4[0], lambda_4[1], }; + lambda_1 = new IntUnaryOperator[] { lambda_4[0], lambda_4[0], lambda_4[0], lambda_4[0], }; + } + + private IntUnaryOperator makeLambda(int a) { + return x -> x + a; + } + + public void process(Blackhole bh, IntUnaryOperator[] operations) { + for (int i = 0; i < LIMIT; i++) { + for (IntUnaryOperator op : operations) { + bh.consume(op.applyAsInt(i)); + } + } + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner1(Blackhole bh) { + process(bh, inner_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner2(Blackhole bh) { + process(bh, inner_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void inner4(Blackhole bh) { + process(bh, inner_4); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda1(Blackhole bh) { + process(bh, lambda_1); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda2(Blackhole bh) { + process(bh, lambda_2); + } + + @Benchmark + @OperationsPerInvocation(OPERATIONS) + public void lambda4(Blackhole bh) { + process(bh, lambda_4); + } + +} + diff --git a/test/micro/classes/org/openjdk/bench/vm/lang/InstanceOf.java b/test/micro/classes/org/openjdk/bench/vm/lang/InstanceOf.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lang/InstanceOf.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.io.Serializable; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * Tests various usages of instanceof. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class InstanceOf { + + private static final int NOOFOBJECTS = 100; + private static final int NULLRATIO = 3; + + public Date[] dateArray; + public Object[] objectArray; + + @Setup + public void setup() { + dateArray = new Date[NOOFOBJECTS * NULLRATIO]; + for (int i = 0; i < NOOFOBJECTS * NULLRATIO; i += NULLRATIO) { + dateArray[i] = new Date(); + } + objectArray = dateArray; + } + + /** + * Performs "instanceof Cloneable" on objects that definitely are of that interface. It is not clear however whether + * the objects are null or not, therefore a simple nullcheck is all that should be left of here. + */ + @Benchmark + @OperationsPerInvocation((NOOFOBJECTS * NULLRATIO)) + public int instanceOfInterfacePartialRemove() { + int dummy = 0; + Date[] localArray = dateArray; + for (int i = 0; i < NOOFOBJECTS * NULLRATIO; i++) { + if (localArray[i] instanceof Cloneable) { + dummy++; + } + } + return dummy; + } + + /** + * Performs three serial instanceof statements on the same object for three different interfaces. The objects are + * 50% null, and all non-null are instanceof the last interface. + */ + @Benchmark + @OperationsPerInvocation((NOOFOBJECTS * NULLRATIO)) + public int instanceOfInterfaceSerial() { + int dummy = 0; + Object[] localArray = objectArray; + for (int i = 0; i < NOOFOBJECTS * NULLRATIO; i++) { + if (localArray[i] instanceof Runnable) { + dummy += 1000; + } else if (localArray[i] instanceof CharSequence) { + dummy += 2000; + } else if (localArray[i] instanceof Serializable) { + dummy++; + } + } + return dummy; + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lang/LockUnlock.java b/test/micro/classes/org/openjdk/bench/vm/lang/LockUnlock.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lang/LockUnlock.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + + +/** + * Benchmark class for simple lock unlock tests. Nothing big should ever go into this class. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class LockUnlock { + + @Param("100") + private int innerCount; + + public Object lockObject1; + public Object lockObject2; + public int factorial; + public int dummyInt1; + public int dummyInt2; + + @Setup + public void setup() { + lockObject1 = new Object(); + lockObject2 = new Object(); + dummyInt1 = 47; + dummyInt2 = 11; // anything + } + + /** Perform a synchronized on a local object within a loop. */ + @Benchmark + public void testSimpleLockUnlock() { + Object localObject = lockObject1; + for (int i = 0; i < innerCount; i++) { + synchronized (localObject) { + dummyInt1++; + dummyInt2++; + } + } + } + + /** Perform a recursive synchronized on a local object within a loop. */ + @Benchmark + public void testRecursiveLockUnlock() { + Object localObject = lockObject1; + for (int i = 0; i < innerCount; i++) { + synchronized (localObject) { + synchronized (localObject) { + dummyInt1++; + dummyInt2++; + } + } + } + } + + /** Perform two synchronized after each other on the same local object. */ + @Benchmark + public void testSerialLockUnlock() { + Object localObject = lockObject1; + for (int i = 0; i < innerCount; i++) { + synchronized (localObject) { + dummyInt1++; + } + synchronized (localObject) { + dummyInt2++; + } + } + } + + /** + * Performs recursive synchronizations on the same local object. + *

+ * Result is 3628800 + */ + @Benchmark + public void testRecursiveSynchronization() { + factorial = fact(10); + } + + private synchronized int fact(int n) { + if (n == 0) { + return 1; + } else { + return fact(n - 1) * n; + } + } +} diff --git a/test/micro/classes/org/openjdk/bench/vm/lang/Throw.java b/test/micro/classes/org/openjdk/bench/vm/lang/Throw.java new file mode 100644 --- /dev/null +++ b/test/micro/classes/org/openjdk/bench/vm/lang/Throw.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Tests throwing exceptions. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Throw { + + public static boolean alwaysTrue = true; + private static Object nullObject = null; + public Object useObject = new Object(); + + @Benchmark + public void throwSyncException(Blackhole bh) { + try { + throwingMethod(); + } catch (Exception ex) { + bh.consume(useObject); + } + } + + @Benchmark + public void throwASyncException(Blackhole bh) { + try { + throwNullpointer(); + } catch (Exception ex) { + bh.consume(useObject); + } + } + + @Benchmark + public void throwSyncExceptionUseException(Blackhole bh) { + try { + throwingMethod(); + } catch (Exception ex) { + bh.consume(ex); + } + } + + @Benchmark + public void throwSyncExceptionUseMessage(Blackhole bh) { + try { + throwingMethod(); + } catch (Exception ex) { + bh.consume(ex.getMessage()); + } + } + + @Benchmark + public void throwSyncExceptionUseStacktrace(Blackhole bh) { + try { + throwingMethod(); + } catch (Exception ex) { + bh.consume(ex.getStackTrace()); + } + } + + @Benchmark + public void throwWith16Frames(Blackhole bh) { + try { + throwingMethod(16); + } catch (Exception ex) { + bh.consume(useObject); + } + } + + @Benchmark + public void throwWith32Frames(Blackhole bh) { + try { + throwingMethod(32); + } catch (Exception ex) { + bh.consume(useObject); + } + } + + @Benchmark + public void throwWith64Frames(Blackhole bh) { + try { + throwingMethod(64); + } catch (Exception ex) { + bh.consume(useObject); + } + } + + public void throwingMethod() throws Exception { + if (alwaysTrue) { + throw new Exception(); + } + } + + public void throwingMethod(int i) throws Exception { + if (i == 0) { + throw new Exception(); + } + throwingMethod(i - 1); + } + + public void throwNullpointer() { + nullObject.hashCode(); + } +}