From 7a30c9775374fe12250226baf12e0354939d1dd2 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Fri, 16 Nov 2018 23:39:51 +0100 Subject: [PATCH] 8061281: Microbenchmark suite build support, directory layout and sample benchmarks 8061282: Migrate jmh-jdk-microbenchmarks into the JDK Co-authored-by: Magnus Ihse Bursie Co-authored-by: Erik Joelsson Co-authored-by: Staffan Friberg Reviewed-by: ecaspole, mchung, erikj, ihse --- doc/testing.html | 24 ++ doc/testing.md | 46 +++ make/Help.gmk | 1 + make/InitSupport.gmk | 2 +- make/Main.gmk | 14 +- make/RunTests.gmk | 163 +++++++- make/autoconf/configure.ac | 3 + make/autoconf/lib-tests.m4 | 62 ++++ make/autoconf/spec.gmk.in | 6 + make/common/FindTests.gmk | 3 + make/common/JarArchive.gmk | 13 +- make/conf/jib-profiles.js | 8 +- make/devkit/createJMHBundle.sh | 50 +++ make/test/BuildMicrobenchmark.gmk | 113 ++++++ .../bench/java/io/BlackholedOutputStream.java | 52 +++ .../bench/java/io/FileChannelRead.java | 87 +++++ .../bench/java/io/FileChannelWrite.java | 87 +++++ .../org/openjdk/bench/java/io/FileRead.java | 84 +++++ .../org/openjdk/bench/java/io/FileWrite.java | 81 ++++ .../bench/java/io/ObjectStreamClasses.java | 244 ++++++++++++ .../bench/java/io/RandomAccessRead.java | 102 +++++ .../bench/java/io/RandomAccessWrite.java | 102 +++++ .../java/io/SerializationWriteReplace.java | 90 +++++ .../micro/org/openjdk/bench/java/io/UTF8.java | 62 ++++ .../openjdk/bench/java/lang/ArrayCopy.java | 180 +++++++++ .../bench/java/lang/ArrayCopyAligned.java | 89 +++++ .../java/lang/ArrayCopyUnalignedBoth.java | 88 +++++ .../java/lang/ArrayCopyUnalignedDst.java | 88 +++++ .../java/lang/ArrayCopyUnalignedSrc.java | 88 +++++ .../openjdk/bench/java/lang/ClassForName.java | 70 ++++ .../org/openjdk/bench/java/lang/Clone.java | 63 ++++ .../bench/java/lang/FloatingDecimal.java | 89 +++++ .../bench/java/lang/GetStackTrace.java | 57 +++ .../org/openjdk/bench/java/lang/Integers.java | 66 ++++ .../org/openjdk/bench/java/lang/Longs.java | 93 +++++ .../openjdk/bench/java/lang/NewInstance.java | 131 +++++++ .../bench/java/lang/ObjectHashCode.java | 82 ++++ .../bench/java/lang/StringBuffers.java | 77 ++++ .../bench/java/lang/StringBuilders.java | 259 +++++++++++++ .../openjdk/bench/java/lang/StringConcat.java | 100 +++++ .../bench/java/lang/StringHashCode.java | 69 ++++ .../openjdk/bench/java/lang/StringHttp.java | 81 ++++ .../bench/java/lang/StringIndexOf.java | 138 +++++++ .../openjdk/bench/java/lang/StringOther.java | 88 +++++ .../bench/java/lang/StringUpperLower.java | 81 ++++ .../org/openjdk/bench/java/lang/Systems.java | 46 +++ .../bench/java/lang/ThreadStartJoin.java | 97 +++++ .../java/lang/invoke/CallSiteSetTarget.java | 208 +++++++++++ .../lang/invoke/CallSiteSetTargetSelf.java | 149 ++++++++ .../java/lang/invoke/CallSiteStable.java | 165 +++++++++ .../bench/java/lang/invoke/LookupAcquire.java | 94 +++++ .../java/lang/invoke/LookupDefaultFind.java | 109 ++++++ .../java/lang/invoke/LookupPublicFind.java | 106 ++++++ .../lang/invoke/MethodHandleAsCollector.java | 103 ++++++ .../lang/invoke/MethodHandleAsSpreader.java | 96 +++++ .../MethodHandleAsVarargsCollector.java | 103 ++++++ .../lang/invoke/MethodHandleBasicInvoke.java | 103 ++++++ .../invoke/MethodHandleBindToBinding.java | 93 +++++ .../lang/invoke/MethodHandleBindToCurry.java | 102 +++++ .../invoke/MethodHandleConvertBoxing.java | 99 +++++ .../lang/invoke/MethodHandleConvertCast.java | 101 +++++ .../MethodHandleConvertReturnPrimitive.java | 96 +++++ .../MethodHandleConvertReturnReference.java | 96 +++++ .../invoke/MethodHandleConvertReturnVoid.java | 96 +++++ .../invoke/MethodHandleConvertUnboxing.java | 98 +++++ .../invoke/MethodHandleConvertWidening.java | 98 +++++ .../invoke/MethodHandleInvokeWithArgs.java | 87 +++++ .../MethodHandleProxiesAsIFInstance.java | 118 ++++++ .../lang/invoke/MethodHandleProxiesSuppl.java | 90 +++++ .../MethodHandlesArrayElementGetter.java | 89 +++++ .../MethodHandlesArrayElementSetter.java | 90 +++++ .../invoke/MethodHandlesCatchException.java | 126 +++++++ .../lang/invoke/MethodHandlesConstant.java | 74 ++++ .../invoke/MethodHandlesDropArguments.java | 90 +++++ .../invoke/MethodHandlesExactInvoker.java | 81 ++++ .../lang/invoke/MethodHandlesFilterArgs.java | 116 ++++++ .../invoke/MethodHandlesFilterReturn.java | 96 +++++ .../invoke/MethodHandlesFoldArguments.java | 96 +++++ .../invoke/MethodHandlesGuardWithTest.java | 98 +++++ .../lang/invoke/MethodHandlesIdentity.java | 74 ++++ .../invoke/MethodHandlesInsertArguments.java | 100 +++++ .../lang/invoke/MethodHandlesInvoker.java | 81 ++++ .../invoke/MethodHandlesPermuteArguments.java | 100 +++++ .../invoke/MethodHandlesSpreadInvoker.java | 89 +++++ .../invoke/MethodHandlesThrowException.java | 113 ++++++ .../java/lang/invoke/MethodTypeAcquire.java | 89 +++++ .../lang/invoke/MethodTypeAppendParams.java | 82 ++++ .../lang/invoke/MethodTypeChangeParam.java | 66 ++++ .../lang/invoke/MethodTypeChangeReturn.java | 66 ++++ .../lang/invoke/MethodTypeDropParams.java | 76 ++++ .../java/lang/invoke/MethodTypeGenerify.java | 81 ++++ .../lang/invoke/MethodTypeInsertParams.java | 76 ++++ .../java/lang/invoke/SwitchPointAdhoc.java | 103 ++++++ .../java/lang/invoke/SwitchPointGuard.java | 99 +++++ .../bench/java/lang/reflect/Clazz.java | 82 ++++ .../reflect/ClazzWithSecurityManager.java | 54 +++ .../bench/java/lang/reflect/MethodInvoke.java | 114 ++++++ .../openjdk/bench/java/math/BigDecimals.java | 226 +++++++++++ .../openjdk/bench/java/math/BigIntegers.java | 140 +++++++ .../bench/java/net/DatagramSocketTest.java | 75 ++++ .../java/net/SocketChannelReadWrite.java | 100 +++++ .../bench/java/net/SocketReadWrite.java | 107 ++++++ .../bench/java/net/SocketStreaming.java | 253 +++++++++++++ .../bench/java/net/URLEncodeDecode.java | 124 +++++++ .../openjdk/bench/java/nio/ByteBuffers.java | 336 +++++++++++++++++ .../bench/java/nio/CharsetEncodeDecode.java | 90 +++++ .../bench/java/security/DoPrivileged.java | 62 ++++ .../bench/java/security/MessageDigests.java | 80 ++++ .../openjdk/bench/java/util/ArraysEquals.java | 96 +++++ .../org/openjdk/bench/java/util/Dates.java | 60 +++ .../bench/java/util/GregorianCalendars.java | 61 +++ .../openjdk/bench/java/util/RandomNext.java | 65 ++++ .../org/openjdk/bench/java/util/ZipFind.java | 108 ++++++ .../bench/java/util/concurrent/Atomic.java | 117 ++++++ .../concurrent/AtomicIntegerUpdateAndGet.java | 116 ++++++ .../util/concurrent/ForkJoinPoolForking.java | 178 +++++++++ .../concurrent/ForkJoinPoolRawCallable.java | 154 ++++++++ .../ForkJoinPoolThresholdAutoQueued.java | 128 +++++++ .../ForkJoinPoolThresholdAutoSurplus.java | 128 +++++++ .../ForkJoinPoolThresholdStatic.java | 129 +++++++ .../bench/java/util/concurrent/Locks.java | 232 ++++++++++++ .../bench/java/util/concurrent/Maps.java | 116 ++++++ .../bench/java/util/concurrent/Problem.java | 78 ++++ .../util/concurrent/ProducerConsumer.java | 134 +++++++ .../bench/java/util/concurrent/Queues.java | 99 +++++ .../concurrent/ThreadLocalRandomNextInt.java | 93 +++++ .../bench/java/util/logging/LogRecord.java | 78 ++++ .../bench/java/util/stream/AllMatcher.java | 98 +++++ .../bench/java/util/stream/AnyMatcher.java | 97 +++++ .../bench/java/util/stream/Decomposition.java | 112 ++++++ .../bench/java/util/stream/NoneMatcher.java | 82 ++++ .../bench/java/util/stream/Reducers.java | 89 +++++ .../java/util/stream/ops/LongAccumulator.java | 45 +++ .../java/util/stream/ops/ref/AllMatch.java | 125 +++++++ .../util/stream/ops/ref/AllMatchShort.java | 113 ++++++ .../java/util/stream/ops/ref/AnyMatch.java | 125 +++++++ .../util/stream/ops/ref/AnyMatchShort.java | 113 ++++++ .../java/util/stream/ops/ref/Filter.java | 137 +++++++ .../java/util/stream/ops/ref/FindAny.java | 57 +++ .../java/util/stream/ops/ref/FindFirst.java | 57 +++ .../java/util/stream/ops/ref/ForEach.java | 126 +++++++ .../bench/java/util/stream/ops/ref/Limit.java | 153 ++++++++ .../bench/java/util/stream/ops/ref/Map.java | 137 +++++++ .../java/util/stream/ops/ref/NoneMatch.java | 125 +++++++ .../util/stream/ops/ref/NoneMatchShort.java | 113 ++++++ .../java/util/stream/ops/ref/Reduce.java | 125 +++++++ .../java/util/stream/ops/ref/ReduceBase.java | 126 +++++++ .../java/util/stream/ops/ref/Sorted.java | 105 ++++++ .../util/stream/ops/ref/SortedUnique.java | 72 ++++ .../util/stream/ops/ref/UniqueElements.java | 91 +++++ .../java/util/stream/ops/value/AllMatch.java | 125 +++++++ .../util/stream/ops/value/AllMatchShort.java | 113 ++++++ .../java/util/stream/ops/value/AnyMatch.java | 124 +++++++ .../util/stream/ops/value/AnyMatchShort.java | 113 ++++++ .../java/util/stream/ops/value/Filter.java | 131 +++++++ .../java/util/stream/ops/value/FindAny.java | 57 +++ .../java/util/stream/ops/value/FindFirst.java | 57 +++ .../java/util/stream/ops/value/ForEach.java | 125 +++++++ .../java/util/stream/ops/value/Limit.java | 142 +++++++ .../bench/java/util/stream/ops/value/Map.java | 131 +++++++ .../java/util/stream/ops/value/NoneMatch.java | 125 +++++++ .../util/stream/ops/value/NoneMatchShort.java | 113 ++++++ .../java/util/stream/ops/value/Reduce.java | 124 +++++++ .../util/stream/ops/value/ReduceBase.java | 125 +++++++ .../java/util/stream/ops/value/Sorted.java | 86 +++++ .../util/stream/ops/value/SortedUnique.java | 71 ++++ .../util/stream/ops/value/UniqueElements.java | 86 +++++ .../stream/pipeline/PipelineParMultiple.java | 134 +++++++ .../stream/pipeline/PipelineSeqMultiple.java | 134 +++++++ .../util/stream/pipeline/PipelineSetup.java | 186 ++++++++++ .../java/util/stream/pipeline/Terminal.java | 151 ++++++++ .../java/util/stream/tasks/DataProviders.java | 43 +++ .../tasks/DictionaryWordValue/Bulk.java | 144 +++++++ .../DictionaryProblem.java | 101 +++++ .../tasks/DictionaryWordValue/Lambda.java | 83 +++++ .../tasks/DictionaryWordValue/Xtras.java | 32 ++ .../stream/tasks/IntegerDuplicate/Bulk.java | 132 +++++++ .../IntegerDuplicateProblem.java | 45 +++ .../stream/tasks/IntegerDuplicate/Lambda.java | 70 ++++ .../util/stream/tasks/IntegerMax/Bulk.java | 126 +++++++ .../tasks/IntegerMax/IntegerMaxProblem.java | 45 +++ .../util/stream/tasks/IntegerMax/Lambda.java | 78 ++++ .../util/stream/tasks/IntegerMax/Xtras.java | 83 +++++ .../util/stream/tasks/IntegerSum/Bulk.java | 124 +++++++ .../tasks/IntegerSum/IntegerSumProblem.java | 45 +++ .../util/stream/tasks/IntegerSum/Lambda.java | 87 +++++ .../util/stream/tasks/IntegerSum/Xtras.java | 34 ++ .../util/stream/tasks/PhoneCode/Bulk.java | 223 +++++++++++ .../tasks/PhoneCode/PhoneCodeProblem.java | 105 ++++++ .../tasks/PrimesFilter/PrimesProblem.java | 74 ++++ .../stream/tasks/PrimesFilter/t100/Bulk.java | 147 ++++++++ .../tasks/PrimesFilter/t100/Lambda.java | 81 ++++ .../stream/tasks/PrimesFilter/t100/Xtras.java | 37 ++ .../tasks/PrimesFilter/t10000/Bulk.java | 147 ++++++++ .../tasks/PrimesFilter/t10000/Lambda.java | 81 ++++ .../tasks/PrimesFilter/t10000/Xtras.java | 37 ++ .../util/stream/tasks/PrimesSieve/Bulk.java | 180 +++++++++ .../tasks/PrimesSieve/PrimesSieveProblem.java | 44 +++ .../bench/java/util/stream/tasks/README | 55 +++ .../org/openjdk/bench/javax/crypto/AES.java | 79 ++++ .../openjdk/bench/javax/crypto/Crypto.java | 112 ++++++ .../org/openjdk/bench/javax/tools/Javac.java | 81 ++++ .../bench/javax/xml/AbstractXMLMicro.java | 99 +++++ .../org/openjdk/bench/javax/xml/DOM.java | 158 ++++++++ .../openjdk/bench/javax/xml/SAXUsingJDK.java | 53 +++ .../org/openjdk/bench/javax/xml/STAX.java | 81 ++++ .../vm/compiler/ArrayBoundCheckRemoval.java | 114 ++++++ .../openjdk/bench/vm/compiler/ArrayClear.java | 60 +++ .../bench/vm/compiler/ArrayStoreCheck.java | 193 ++++++++++ .../openjdk/bench/vm/compiler/CopyLoop.java | 149 ++++++++ .../org/openjdk/bench/vm/compiler/DivRem.java | 217 +++++++++++ .../openjdk/bench/vm/compiler/Explosion.java | 68 ++++ .../bench/vm/compiler/InnerClassNullRef.java | 95 +++++ .../bench/vm/compiler/InterfaceCalls.java | 287 ++++++++++++++ .../bench/vm/compiler/Multiplication.java | 118 ++++++ .../vm/compiler/PostAllocationStores.java | 129 +++++++ .../openjdk/bench/vm/compiler/SpillCode.java | 204 ++++++++++ .../bench/vm/compiler/StoreAfterStore.java | 127 +++++++ .../openjdk/bench/vm/compiler/Straighten.java | 248 +++++++++++++ .../bench/vm/compiler/WriteBarrier.java | 162 ++++++++ test/micro/org/openjdk/bench/vm/gc/Alloc.java | 97 +++++ .../bench/vm/lambda/capture/Capture0.java | 289 +++++++++++++++ .../bench/vm/lambda/capture/Capture2.java | 101 +++++ .../bench/vm/lambda/capture/CaptureMR.java | 102 +++++ .../lambda/capture/FunctionalInterface0.java | 35 ++ .../lambda/capture/FunctionalInterface1.java | 35 ++ .../vm/lambda/chain/ChainAnonymCap0.java | 162 ++++++++ .../vm/lambda/chain/ChainAnonymCap1.java | 162 ++++++++ .../vm/lambda/chain/ChainAnonymCap4.java | 162 ++++++++ .../bench/vm/lambda/chain/ChainBase.java | 37 ++ .../vm/lambda/chain/ChainLambdaCap0.java | 117 ++++++ .../vm/lambda/chain/ChainLambdaCap1.java | 117 ++++++ .../vm/lambda/chain/ChainLambdaCap4.java | 117 ++++++ .../bench/vm/lambda/chain/ChainMrefBound.java | 117 ++++++ .../vm/lambda/chain/ChainMrefUnbound.java | 117 ++++++ .../openjdk/bench/vm/lambda/chain/Level.java | 35 ++ .../bench/vm/lambda/chain/TopLevel.java | 38 ++ .../bench/vm/lambda/invoke/AckermannI.java | 112 ++++++ .../bench/vm/lambda/invoke/AckermannL.java | 127 +++++++ .../bench/vm/lambda/invoke/Function0.java | 180 +++++++++ .../bench/vm/lambda/invoke/Function1.java | 350 ++++++++++++++++++ .../bench/vm/lambda/invoke/Morph0.java | 257 +++++++++++++ .../bench/vm/lambda/invoke/Morph1.java | 157 ++++++++ .../bench/vm/lambda/invoke/Morph2.java | 149 ++++++++ .../org/openjdk/bench/vm/lang/InstanceOf.java | 98 +++++ .../org/openjdk/bench/vm/lang/LockUnlock.java | 119 ++++++ .../org/openjdk/bench/vm/lang/Throw.java | 135 +++++++ 247 files changed, 26097 insertions(+), 13 deletions(-) create mode 100644 make/devkit/createJMHBundle.sh create mode 100644 make/test/BuildMicrobenchmark.gmk create mode 100644 test/micro/org/openjdk/bench/java/io/BlackholedOutputStream.java create mode 100644 test/micro/org/openjdk/bench/java/io/FileChannelRead.java create mode 100644 test/micro/org/openjdk/bench/java/io/FileChannelWrite.java create mode 100644 test/micro/org/openjdk/bench/java/io/FileRead.java create mode 100644 test/micro/org/openjdk/bench/java/io/FileWrite.java create mode 100644 test/micro/org/openjdk/bench/java/io/ObjectStreamClasses.java create mode 100644 test/micro/org/openjdk/bench/java/io/RandomAccessRead.java create mode 100644 test/micro/org/openjdk/bench/java/io/RandomAccessWrite.java create mode 100644 test/micro/org/openjdk/bench/java/io/SerializationWriteReplace.java create mode 100644 test/micro/org/openjdk/bench/java/io/UTF8.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ArrayCopy.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ArrayCopyAligned.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ClassForName.java create mode 100644 test/micro/org/openjdk/bench/java/lang/Clone.java create mode 100644 test/micro/org/openjdk/bench/java/lang/FloatingDecimal.java create mode 100644 test/micro/org/openjdk/bench/java/lang/GetStackTrace.java create mode 100644 test/micro/org/openjdk/bench/java/lang/Integers.java create mode 100644 test/micro/org/openjdk/bench/java/lang/Longs.java create mode 100644 test/micro/org/openjdk/bench/java/lang/NewInstance.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ObjectHashCode.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringBuffers.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringBuilders.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringConcat.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringHashCode.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringHttp.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringIndexOf.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringOther.java create mode 100644 test/micro/org/openjdk/bench/java/lang/StringUpperLower.java create mode 100644 test/micro/org/openjdk/bench/java/lang/Systems.java create mode 100644 test/micro/org/openjdk/bench/java/lang/ThreadStartJoin.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/CallSiteStable.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/LookupAcquire.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java create mode 100644 test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java create mode 100644 test/micro/org/openjdk/bench/java/lang/reflect/Clazz.java create mode 100644 test/micro/org/openjdk/bench/java/lang/reflect/ClazzWithSecurityManager.java create mode 100644 test/micro/org/openjdk/bench/java/lang/reflect/MethodInvoke.java create mode 100644 test/micro/org/openjdk/bench/java/math/BigDecimals.java create mode 100644 test/micro/org/openjdk/bench/java/math/BigIntegers.java create mode 100644 test/micro/org/openjdk/bench/java/net/DatagramSocketTest.java create mode 100644 test/micro/org/openjdk/bench/java/net/SocketChannelReadWrite.java create mode 100644 test/micro/org/openjdk/bench/java/net/SocketReadWrite.java create mode 100644 test/micro/org/openjdk/bench/java/net/SocketStreaming.java create mode 100644 test/micro/org/openjdk/bench/java/net/URLEncodeDecode.java create mode 100644 test/micro/org/openjdk/bench/java/nio/ByteBuffers.java create mode 100644 test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java create mode 100644 test/micro/org/openjdk/bench/java/security/DoPrivileged.java create mode 100644 test/micro/org/openjdk/bench/java/security/MessageDigests.java create mode 100644 test/micro/org/openjdk/bench/java/util/ArraysEquals.java create mode 100644 test/micro/org/openjdk/bench/java/util/Dates.java create mode 100644 test/micro/org/openjdk/bench/java/util/GregorianCalendars.java create mode 100644 test/micro/org/openjdk/bench/java/util/RandomNext.java create mode 100644 test/micro/org/openjdk/bench/java/util/ZipFind.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/Atomic.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/Locks.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/Maps.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/Problem.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/Queues.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java create mode 100644 test/micro/org/openjdk/bench/java/util/logging/LogRecord.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/AllMatcher.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/AnyMatcher.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/Decomposition.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/NoneMatcher.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/Reducers.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/Filter.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/Limit.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/Map.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/Filter.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/FindAny.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/ForEach.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/Limit.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/Map.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/Reduce.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/Sorted.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/pipeline/Terminal.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java create mode 100644 test/micro/org/openjdk/bench/java/util/stream/tasks/README create mode 100644 test/micro/org/openjdk/bench/javax/crypto/AES.java create mode 100644 test/micro/org/openjdk/bench/javax/crypto/Crypto.java create mode 100644 test/micro/org/openjdk/bench/javax/tools/Javac.java create mode 100644 test/micro/org/openjdk/bench/javax/xml/AbstractXMLMicro.java create mode 100644 test/micro/org/openjdk/bench/javax/xml/DOM.java create mode 100644 test/micro/org/openjdk/bench/javax/xml/SAXUsingJDK.java create mode 100644 test/micro/org/openjdk/bench/javax/xml/STAX.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/ArrayClear.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/CopyLoop.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/DivRem.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/Explosion.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/InnerClassNullRef.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/Multiplication.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/PostAllocationStores.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/SpillCode.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/StoreAfterStore.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/Straighten.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/WriteBarrier.java create mode 100644 test/micro/org/openjdk/bench/vm/gc/Alloc.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/capture/Capture0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/capture/Capture2.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/capture/CaptureMR.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainBase.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/Level.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/chain/TopLevel.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannI.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannL.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/Function0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/Function1.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/Morph0.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/Morph1.java create mode 100644 test/micro/org/openjdk/bench/vm/lambda/invoke/Morph2.java create mode 100644 test/micro/org/openjdk/bench/vm/lang/InstanceOf.java create mode 100644 test/micro/org/openjdk/bench/vm/lang/LockUnlock.java create mode 100644 test/micro/org/openjdk/bench/vm/lang/Throw.java diff --git a/doc/testing.html b/doc/testing.html index 81d8972258f..494550f478b 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -24,12 +24,14 @@
  • Test selection
  • Test results and summary
  • Test suite control
  • @@ -44,9 +46,11 @@ $ make test TEST=jdk_lang $ make test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1" $ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug" $ make test TEST="jtreg:test/hotspot:hotspot_gc test/hotspot/jtreg/native_sanity/JniVersion.java" +$ make test TEST="micro:java.lang.reflect" MICRO="FORK=1;WARMUP_ITER=2" $ make exploded-test TEST=tier2

    Configuration

    To be able to run JTReg tests, configure needs to know where to find the JTReg test framework. If it is not picked up automatically by configure, use the --with-jtreg=<path to jtreg home> option to point to the JTReg framework. Note that this option should point to the JTReg home, i.e. the top directory, containing lib/jtreg.jar etc. (An alternative is to set the JT_HOME environment variable to point to the JTReg home before running configure.)

    +

    To be able to run microbenchmarks, configure needs to know where to find the JMH dependency. Use --with-jmh=<path to JMH jars> to point to a directory containing the core JMH and transitive dependencies. The recommended dependencies can be retrieved by running sh make/devkit/createJMHBundle.sh, after which --with-jmh=build/jmh/jars should work.

    Test selection

    All functionality is available using the test make target. In this use case, the test or tests to be executed is controlled using the TEST variable. To speed up subsequent test runs with no source code changes, test-only can be used instead, which do not depend on the source and test image build.

    For some common top-level tests, direct make targets have been generated. This includes all JTReg test groups, the hotspot gtest, and custom tests (if present). This means that make test-tier1 is equivalent to make test TEST="tier1", but the latter is more tab-completion friendly. For more complex test runs, the test TEST="x" solution needs to be used.

    @@ -61,6 +65,9 @@ $ make exploded-test TEST=tier2

    Since the Hotspot Gtest suite is so quick, the default is to run all tests. This is specified by just gtest, or as a fully qualified test descriptor gtest:all.

    If you want, you can single out an individual test or a group of tests, for instance gtest:LogDecorations or gtest:LogDecorations.level_test_vm. This can be particularly useful if you want to run a shaky test repeatedly.

    For Gtest, there is a separate test suite for each JVM variant. The JVM variant is defined by adding /<variant> to the test descriptor, e.g. gtest:Log/client. If you specify no variant, gtest will run once for each JVM variant present (e.g. server, client). So if you only have the server JVM present, then gtest:all will be equivalent to gtest:all/server.

    +

    Microbenchmarks

    +

    Which microbenchmarks to run is selected using a regular expression following the micro: test descriptor, e.g., micro:java.lang.reflect. This delegates the test selection to JMH, meaning package name, class name and even benchmark method names can be used to select tests.

    +

    Using special characters like | in the regular expression is possible, but needs to be escaped multiple times: micro:ArrayCopy\\\\\|reflect.

    Special tests

    A handful of odd tests that are not covered by any other testing framework are accessible using the special: test descriptor. Currently, this includes failure-handler and make.

      @@ -127,5 +134,22 @@ TEST FAILURE

      OPTIONS

      Additional options to the Gtest test framework.

      Use GTEST="OPTIONS=--help" to see all available Gtest options.

      +

      Microbenchmark keywords

      +

      FORK

      +

      Override the number of benchmark forks to spawn. Same as specifying -f <num>.

      +

      ITER

      +

      Number of measurement iterations per fork. Same as specifying -i <num>.

      +

      TIME

      +

      Amount of time to spend in each measurement iteration, in seconds. Same as specifying -r <num>

      +

      WARMUP_ITER

      +

      Number of warmup iterations to run before the measurement phase in each fork. Same as specifying -wi <num>.

      +

      WARMUP_TIME

      +

      Amount of time to spend in each warmup iteration. Same as specifying -w <num>.

      +

      RESULTS_FORMAT

      +

      Specify to have the test run save a log of the values. Accepts the same values as -rff, i.e., text, csv, scsv, json, or latex.

      +

      VM_OPTIONS

      +

      Additional VM arguments to provide to forked off VMs. Same as -jvmArgs <args>

      +

      OPTIONS

      +

      Additional arguments to send to JMH.

      diff --git a/doc/testing.md b/doc/testing.md index 1b813c993ce..70f648cc6c7 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -26,6 +26,7 @@ Some example command-lines: $ make test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1" $ make test TEST="hotspot:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug" $ make test TEST="jtreg:test/hotspot:hotspot_gc test/hotspot/jtreg/native_sanity/JniVersion.java" + $ make test TEST="micro:java.lang.reflect" MICRO="FORK=1;WARMUP_ITER=2" $ make exploded-test TEST=tier2 ### Configuration @@ -37,6 +38,12 @@ Note that this option should point to the JTReg home, i.e. the top directory, containing `lib/jtreg.jar` etc. (An alternative is to set the `JT_HOME` environment variable to point to the JTReg home before running `configure`.) +To be able to run microbenchmarks, `configure` needs to know where to find +the JMH dependency. Use `--with-jmh=` to point to a directory +containing the core JMH and transitive dependencies. The recommended dependencies +can be retrieved by running `sh make/devkit/createJMHBundle.sh`, after which +`--with-jmh=build/jmh/jars` should work. + ## Test selection All functionality is available using the `test` make target. In this use case, @@ -104,6 +111,16 @@ is defined by adding `/` to the test descriptor, e.g. variant present (e.g. server, client). So if you only have the server JVM present, then `gtest:all` will be equivalent to `gtest:all/server`. +### Microbenchmarks + +Which microbenchmarks to run is selected using a regular expression +following the `micro:` test descriptor, e.g., `micro:java.lang.reflect`. This +delegates the test selection to JMH, meaning package name, class name and even +benchmark method names can be used to select tests. + +Using special characters like `|` in the regular expression is possible, but +needs to be escaped multiple times: `micro:ArrayCopy\\\\\|reflect`. + ### Special tests A handful of odd tests that are not covered by any other testing framework are @@ -253,6 +270,35 @@ Additional options to the Gtest test framework. Use `GTEST="OPTIONS=--help"` to see all available Gtest options. +### Microbenchmark keywords + +#### FORK +Override the number of benchmark forks to spawn. Same as specifying `-f `. + +#### ITER +Number of measurement iterations per fork. Same as specifying `-i `. + +#### TIME +Amount of time to spend in each measurement iteration, in seconds. Same as +specifying `-r ` + +#### WARMUP_ITER +Number of warmup iterations to run before the measurement phase in each fork. +Same as specifying `-wi `. + +#### WARMUP_TIME +Amount of time to spend in each warmup iteration. Same as specifying `-w `. + +#### RESULTS_FORMAT +Specify to have the test run save a log of the values. Accepts the same values +as `-rff`, i.e., `text`, `csv`, `scsv`, `json`, or `latex`. + +#### VM_OPTIONS +Additional VM arguments to provide to forked off VMs. Same as `-jvmArgs ` + +#### OPTIONS +Additional arguments to send to JMH. + --- # Override some definitions in the global css file that are not optimal for # this document. diff --git a/make/Help.gmk b/make/Help.gmk index 7fe15453249..76b87669093 100644 --- a/make/Help.gmk +++ b/make/Help.gmk @@ -103,6 +103,7 @@ help: $(info $(_) # make test TEST="jdk_lang gtest:all") $(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness) $(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness) + $(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness) $(info $(_) TEST_OPTS="OPT1=x;..." # Generic control of all test harnesses) $(info $(_) TEST_VM_OPTS="ARG ..." # Same as setting TEST_OPTS to VM_OPTIONS="ARG ...") $(info ) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 1bf64a0982b..f038476c071 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -50,7 +50,7 @@ ifeq ($(HAS_SPEC),) # Make control variables, handled by Init.gmk INIT_CONTROL_VARIABLES += LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \ - COMPARE_BUILD JTREG GTEST TEST_OPTS TEST_VM_OPTS + COMPARE_BUILD JTREG GTEST MICRO TEST_OPTS TEST_VM_OPTS # All known make control variables MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER diff --git a/make/Main.gmk b/make/Main.gmk index 4dae54895c9..8745996c128 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -493,7 +493,7 @@ ALL_EXPLODED_TEST_TARGETS := $(addprefix exploded-test-, $(ALL_EXPLODED_TESTS)) ALL_TARGETS += $(ALL_TEST_TARGETS) $(ALL_EXPLODED_TEST_TARGETS) ################################################################################ -# Build tests +# Build tests and microbenchmarks # prepare-test-image: @@ -543,11 +543,15 @@ ifeq ($(BUILD_FAILURE_HANDLER), true) -f BuildFailureHandler.gmk images) endif +build-microbenchmark: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f test/BuildMicrobenchmark.gmk) + ALL_TARGETS += prepare-test-image build-test-hotspot-jtreg-native \ test-image-hotspot-jtreg-native build-test-jdk-jtreg-native \ test-image-jdk-jtreg-native build-test-lib build-test-failure-handler \ test-failure-handler test-image-failure-handler test-image-hotspot-gtest \ - test-image-hotspot-jtreg-graal build-test-hotspot-jtreg-graal + test-image-hotspot-jtreg-graal build-test-hotspot-jtreg-graal \ + build-microbenchmark ################################################################################ # Run tests @@ -789,6 +793,8 @@ else jrtfs-jar: interim-langtools + build-microbenchmark: interim-langtools jdk.unsupported java.management + ifeq ($(ENABLE_GENERATE_CLASSLIST), true) ifeq ($(CREATE_BUILDJDK), true) # If creating a buildjdk, the interim image needs to be based on that. @@ -1023,6 +1029,10 @@ test-image: prepare-test-image \ test-image-jdk-jtreg-native test-image-failure-handler \ test-image-demos-jdk $(JVM_TEST_IMAGE_TARGETS) +ifneq ($(JMH_CORE_JAR), ) + test-image: build-microbenchmark +endif + ################################################################################ # all-images builds all our deliverables as images. diff --git a/make/RunTests.gmk b/make/RunTests.gmk index ff61fe85d51..29be126de3a 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -237,13 +237,11 @@ ifneq ($(TEST_OPTS), ) $(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)') endif +### Jtreg + $(eval $(call SetTestOpt,VM_OPTIONS,JTREG)) $(eval $(call SetTestOpt,JAVA_OPTIONS,JTREG)) -$(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) -$(eval $(call SetTestOpt,JAVA_OPTIONS,GTEST)) - $(eval $(call SetTestOpt,AOT_MODULES,JTREG)) -$(eval $(call SetTestOpt,AOT_MODULES,GTEST)) $(eval $(call SetTestOpt,JOBS,JTREG)) $(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG)) @@ -259,6 +257,12 @@ ifneq ($(JTREG), ) $(info Running tests using JTREG control variable '$(JTREG)') endif +### Gtest + +$(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,GTEST)) +$(eval $(call SetTestOpt,AOT_MODULES,GTEST)) + $(eval $(call ParseKeywordVariable, GTEST, \ SINGLE_KEYWORDS := REPEAT AOT_MODULES, \ STRING_KEYWORDS := OPTIONS VM_OPTIONS JAVA_OPTIONS, \ @@ -269,6 +273,21 @@ ifneq ($(GTEST), ) $(info Running tests using GTEST control variable '$(GTEST)') endif +### Microbenchmarks + +$(eval $(call SetTestOpt,VM_OPTIONS,MICRO)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,MICRO)) + +$(eval $(call ParseKeywordVariable, MICRO, \ + SINGLE_KEYWORDS := ITER FORK TIME WARMUP_ITER WARMUP_TIME, \ + STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS RESULTS_FORMAT TEST_JDK BENCHMARKS_JAR, \ +)) + +ifneq ($(MICRO), ) + # Inform the user + $(info Running tests using MICRO control variable '$(MICRO)') +endif + ################################################################################ # Component-specific Jtreg settings @@ -325,6 +344,24 @@ define ParseGtestTestSelection ) endef +# Helper function to determine if a test specification is a microbenchmark test +# +# It is a microbenchmark test if it is either "micro", or "micro:" followed by an optional +# test filter string. +define ParseMicroTestSelection + $(if $(filter micro%, $1), \ + $(if $(filter micro, $1), \ + micro:all \ + , \ + $(if $(filter micro:, $1), \ + micro:all \ + , \ + $1 \ + ) \ + ) \ + ) +endef + # Helper function that removes the TOPDIR part CleanupJtregPath = \ $(strip $(patsubst %/, %, $(subst $(JTREG_TOPDIR)/,, $1))) @@ -437,6 +474,9 @@ $(foreach test, $(TEST), \ $(if $(strip $(PARSED_TESTS)), , \ $(eval PARSED_TESTS += $(call ParseGtestTestSelection, $(test))) \ ) \ + $(if $(strip $(PARSED_TESTS)), , \ + $(eval PARSED_TESTS += $(call ParseMicroTestSelection, $(test))) \ + ) \ $(if $(strip $(PARSED_TESTS)), , \ $(eval PARSED_TESTS += $(call ParseJtregTestSelection, $(test))) \ ) \ @@ -560,6 +600,113 @@ endef ################################################################################ +### Rules for Microbenchmarks + +# Helper function for SetupRunMicroTest. Set a MICRO_* variable from, in order: +# 1) Specified by user on command line +# 2) Generic default +# +# Note: No spaces are allowed around the arguments. +# Arg $1 The test ID (i.e. $1 in SetupRunMicroTest) +# Arg $2 Base variable, e.g. MICRO_TEST_JDK +# Arg $3 The default value (optional) +define SetMicroValue + ifneq ($$($2), ) + $1_$2 := $$($2) + else + ifneq ($3, ) + $1_$2 := $3 + endif + endif +endef + +SetupRunMicroTest = $(NamedParamsMacroTemplate) +define SetupRunMicroTestBody + $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1 + $1_TEST_SUPPORT_DIR := $$(TEST_SUPPORT_DIR)/$1 + $1_EXITCODE := $$($1_TEST_RESULTS_DIR)/exitcode.txt + + $1_TEST_NAME := $$(strip $$(patsubst micro:%, %, $$($1_TEST))) + + $$(eval $$(call SetMicroValue,$1,MICRO_BENCHMARKS_JAR,$$(TEST_IMAGE_DIR)/micro/benchmarks.jar)) + $$(eval $$(call SetMicroValue,$1,MICRO_TEST_JDK,$$(JDK_IMAGE_DIR))) + $$(eval $$(call SetMicroValue,$1,MICRO_JAVA_OPTIONS)) + + # Current tests needs to open java.io + $1_MICRO_JAVA_OPTIONS += --add-opens=java.base/java.io=ALL-UNNAMED + + # Save output as JSON or CSV file + ifneq ($$(MICRO_RESULTS_FORMAT), ) + $1_MICRO_BASIC_OPTIONS += -rf $$(MICRO_RESULTS_FORMAT) -rff $$($1_TEST_RESULTS_DIR)/jmh-result.$(MICRO_RESULTS_FORMAT) + endif + + ifneq ($$(MICRO_VM_OPTIONS)$$(MICRO_JAVA_OPTIONS), ) + $1_MICRO_VM_OPTIONS := -jvmArgs $$(MICRO_VM_OPTIONS) $$(MICRO_JAVA_OPTIONS) + endif + + ifneq ($$(MICRO_ITER), ) + $1_MICRO_ITER := -i $$(MICRO_ITER) + endif + ifneq ($$(MICRO_FORK), ) + $1_MICRO_FORK := -f $$(MICRO_FORK) + endif + ifneq ($$(MICRO_TIME), ) + $1_MICRO_TIME := -r $$(MICRO_TIME) + endif + ifneq ($$(MICRO_WARMUP_ITER), ) + $1_MICRO_WARMUP_ITER := -wi $$(MICRO_WARMUP_ITER) + endif + ifneq ($$(MICRO_WARMUP_TIME), ) + $1_MICRO_WARMUP_TIME := -w $$(MICRO_WARMUP_TIME) + endif + + run-test-$1: + $$(call LogWarn) + $$(call LogWarn, Running test '$$($1_TEST)') + $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) + $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/micro, \ + $$($1_MICRO_TEST_JDK)/bin/java $$($1_MICRO_JAVA_OPTIONS) -jar $$($1_MICRO_BENCHMARKS_JAR) \ + $$($1_MICRO_ITER) $$($1_MICRO_FORK) $$($1_MICRO_TIME) \ + $$($1_MICRO_WARMUP_ITER) $$($1_MICRO_WARMUP_TIME) \ + $$($1_MICRO_VM_OPTIONS) $$($1_MICRO_BASIC_OPTIONS) $$(MICRO_OPTIONS) \ + $$($1_TEST_NAME) \ + > >($(TEE) $$($1_TEST_RESULTS_DIR)/micro.txt) \ + && $$(ECHO) $$$$? > $$($1_EXITCODE) \ + || $$(ECHO) $$$$? > $$($1_EXITCODE) \ + ) + + $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/micro.txt + + parse-test-$1: run-test-$1 + $$(call LogWarn, Finished running test '$$($1_TEST)') + $$(call LogWarn, Test report is stored in $$(strip \ + $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR)))) + $$(if $$(wildcard $$($1_EXITCODE)), \ + $$(eval $1_EXIT_CODE := $$(shell $$(CAT) $$($1_EXITCODE))) \ + $$(if $$(filter 0, $$($1_EXIT_CODE)), \ + $$(eval $1_PASSED := 1) \ + $$(eval $1_ERROR := 0) \ + , \ + $$(eval $1_PASSED := 0) \ + $$(eval $1_ERROR := 1) \ + ) \ + $$(eval $1_FAILED := 0) \ + $$(eval $1_TOTAL := $$(shell \ + $$(EXPR) $$($1_PASSED) + $$($1_ERROR))) \ + , \ + $$(eval $1_PASSED := 0) \ + $$(eval $1_FAILED := 0) \ + $$(eval $1_ERROR := 1) \ + $$(eval $1_TOTAL := 1) \ + ) + + $1: run-test-$1 parse-test-$1 + + TARGETS += $1 +endef + +################################################################################ + ### Rules for Jtreg # Helper function for SetupRunJtregTest. Set a JTREG_* variable from, in order: @@ -849,6 +996,9 @@ endef UseGtestTestHandler = \ $(if $(filter gtest:%, $1), true) +UseMicroTestHandler = \ + $(if $(filter micro:%, $1), true) + UseJtregTestHandler = \ $(if $(filter jtreg:%, $1), true) @@ -870,6 +1020,11 @@ $(foreach test, $(TESTS_TO_RUN), \ TEST := $(test), \ )) \ ) \ + $(if $(call UseMicroTestHandler, $(test)), \ + $(eval $(call SetupRunMicroTest, $(TEST_ID), \ + TEST := $(test), \ + )) \ + ) \ $(if $(call UseJtregTestHandler, $(test)), \ $(eval $(call SetupRunJtregTest, $(TEST_ID), \ TEST := $(test), \ diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index b579af3e697..f326555b4ae 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -180,6 +180,9 @@ TOOLCHAIN_MISC_CHECKS # Setup the JTReg Regression Test Harness. TOOLCHAIN_SETUP_JTREG +# Setup the Java Microbenchmark Harness (JMH) +LIB_TESTS_SETUP_JMH + # Setup Jib dependency tool TOOLCHAIN_SETUP_JIB diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 15b0a0df443..043d94a7a84 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -55,3 +55,65 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_GRAALUNIT], AC_SUBST(GRAALUNIT_LIB) ]) +############################################################################### +# +# Setup and check the Java Microbenchmark Harness +# +AC_DEFUN_ONCE([LIB_TESTS_SETUP_JMH], +[ + AC_ARG_WITH(jmh, [AS_HELP_STRING([--with-jmh], + [Java Microbenchmark Harness for building the OpenJDK Microbenchmark Suite])]) + + AC_MSG_CHECKING([for jmh (Java Microbenchmark Harness)]) + if test "x$with_jmh" = xno || test "x$with_jmh" = x; then + AC_MSG_RESULT([no, disabled]) + elif test "x$with_jmh" = xyes; then + AC_MSG_RESULT([no, error]) + AC_MSG_ERROR([--with-jmh requires a directory containing all jars needed by JMH]) + else + # Path specified + JMH_HOME="$with_jmh" + if test ! -d [$JMH_HOME]; then + AC_MSG_RESULT([no, error]) + AC_MSG_ERROR([$JMH_HOME does not exist or is not a directory]) + fi + BASIC_FIXUP_PATH([JMH_HOME]) + + jar_names="jmh-core jmh-generator-annprocess jopt-simple commons-math3" + for jar in $jar_names; do + found_jar_files=$($ECHO $(ls $JMH_HOME/$jar-*.jar 2> /dev/null)) + + if test "x$found_jar_files" = x; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([--with-jmh does not contain $jar-*.jar]) + elif ! test -e "$found_jar_files"; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([--with-jmh contain multiple $jar-*.jar: $found_jar_files]) + fi + + found_jar_var_name=found_${jar//-/_} + eval $found_jar_var_name='"'$found_jar_files'"' + done + AC_MSG_RESULT([yes]) + + JMH_CORE_JAR=$found_jmh_core + JMH_GENERATOR_JAR=$found_jmh_generator_annprocess + JMH_JOPT_SIMPLE_JAR=$found_jopt_simple + JMH_COMMONS_MATH_JAR=$found_commons_math3 + + + if [ [[ "$JMH_CORE_JAR" =~ jmh-core-(.*)\.jar$ ]] ] ; then + JMH_VERSION=${BASH_REMATCH[[1]]} + else + JMH_VERSION=unknown + fi + + AC_MSG_NOTICE([JMH core version: $JMH_VERSION]) + fi + + AC_SUBST(JMH_CORE_JAR) + AC_SUBST(JMH_GENERATOR_JAR) + AC_SUBST(JMH_JOPT_SIMPLE_JAR) + AC_SUBST(JMH_COMMONS_MATH_JAR) + AC_SUBST(JMH_VERSION) +]) diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index aec35664ac9..fadbe07b5d9 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -355,6 +355,12 @@ ENABLE_LIBFFI_BUNDLING:=@ENABLE_LIBFFI_BUNDLING@ LIBFFI_LIB_FILE:=@LIBFFI_LIB_FILE@ GRAALUNIT_LIB := @GRAALUNIT_LIB@ +JMH_CORE_JAR := @JMH_CORE_JAR@ +JMH_GENERATOR_JAR := @JMH_GENERATOR_JAR@ +JMH_JOPT_SIMPLE_JAR := @JMH_JOPT_SIMPLE_JAR@ +JMH_COMMONS_MATH_JAR := @JMH_COMMONS_MATH_JAR@ +JMH_VERSION := @JMH_VERSION@ + # Source file for cacerts CACERTS_FILE=@CACERTS_FILE@ diff --git a/make/common/FindTests.gmk b/make/common/FindTests.gmk index 7c27c82b0a6..26525aec80c 100644 --- a/make/common/FindTests.gmk +++ b/make/common/FindTests.gmk @@ -72,6 +72,9 @@ ALL_NAMED_TESTS += $(JTREG_TEST_GROUPS) # Add Gtest ALL_NAMED_TESTS += gtest +# Add microbenchmarks +ALL_NAMED_TESTS += micro + # Find make test targets MAKE_TEST_TARGETS := $(shell $(MAKE) -s --no-print-directory $(MAKE_ARGS) \ SPEC=$(SPEC) -f $(TOPDIR)/test/make/TestMake.gmk print-targets) diff --git a/make/common/JarArchive.gmk b/make/common/JarArchive.gmk index daa1bb4b249..839d2d76924 100644 --- a/make/common/JarArchive.gmk +++ b/make/common/JarArchive.gmk @@ -43,6 +43,7 @@ FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST # For this to work, the source files must exist when the makefile is # parsed. # SRCS:=List of directories in where to find files to add to archive +# BIN:=Directory where to store build control files # SUFFIXES:=File suffixes to include in jar # INCLUDES:=List of directories/packages in SRCS that should be included # EXCLUDES:=List of directories/packages in SRCS that should be excluded @@ -62,10 +63,11 @@ define SetupJarArchiveBody $1_JARMAIN:=$(strip $$($1_JARMAIN)) $1_JARNAME:=$$(notdir $$($1_JAR)) - $1_MANIFEST_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_manifest - $1_DELETESS_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletess - $1_DELETES_FILE:=$$(dir $$($1_JAR))_the.$$($1_JARNAME)_deletes - $1_BIN:=$$(dir $$($1_JAR)) + $1_JAR_OUTPUT_DIR := $$(patsubst %/, %, $$(dir $$($1_JAR))) + $$(call SetIfEmpty, $1_BIN, $$($1_JAR_OUTPUT_DIR)) + $1_MANIFEST_FILE:=$$($1_BIN)/_the.$$($1_JARNAME)_manifest + $1_DELETESS_FILE:=$$($1_BIN)/_the.$$($1_JARNAME)_deletess + $1_DELETES_FILE:=$$($1_BIN)/_the.$$($1_JARNAME)_deletes $$(call SetIfEmpty, $1_JAR_CMD, $$(JAR)) ifeq (,$$($1_SUFFIXES)) @@ -231,11 +233,12 @@ define SetupJarArchiveBody $1_VARDEPS := $$($1_JAR_CMD) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \ $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \ $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES) - $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps) + $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$$($1_JARNAME).vardeps) # Here is the rule that creates/updates the jar file. $$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE) $$(call MakeTargetDir) + $$(call MakeDir, $$($1_BIN)) $$($1_GREP_INCLUDE_OUTPUT) $$($1_GREP_EXCLUDE_OUTPUT) # If the vardeps file is part of the newer prereq list, it means that diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 3447861a39f..bfaef64a773 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -243,7 +243,7 @@ var getJibProfilesCommon = function (input, data) { // These are the base setttings for all the main build profiles. common.main_profile_base = { - dependencies: ["boot_jdk", "gnumake", "jtreg", "jib", "autoconf"], + dependencies: ["boot_jdk", "gnumake", "jtreg", "jib", "autoconf", "jmh"], default_make_targets: ["product-bundles", "test-bundles"], configure_args: concat(["--enable-jtreg-failure-handler"], "--with-exclude-translations=de,es,fr,it,ko,pt_BR,sv,ca,tr,cs,sk,ja_JP_A,ja_JP_HA,ja_JP_HI,ja_JP_I,zh_TW,zh_HK", @@ -892,6 +892,12 @@ var getJibProfilesDependencies = function (input, common) { environment_path: input.get("jtreg", "install_path") + "/jtreg/bin" }, + jmh: { + organization: common.organization, + ext: "tar.gz", + revision: "1.21+1.0" + }, + gnumake: { organization: common.organization, ext: "tar.gz", diff --git a/make/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh new file mode 100644 index 00000000000..a9beaf27b4e --- /dev/null +++ b/make/devkit/createJMHBundle.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e +# +# 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. +# +# Create a bundle in the build directory, containing what's needed to +# build and run JMH microbenchmarks from the OpenJDK build. + +JMH_VERSION=1.21 +COMMONS_MATH3_VERSION=3.2 +JOPT_SIMPLE_VERSION=4.6 + +BUNDLE_NAME=jmh-$JMH_VERSION.tar.gz + +SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)" +BUILD_DIR="${SCRIPT_DIR}/../../build/jmh" +JAR_DIR="$BUILD_DIR/jars" + +mkdir -p $BUILD_DIR $JAR_DIR +cd $JAR_DIR +rm -f * + +wget http://central.maven.org/maven2/org/apache/commons/commons-math3/$COMMONS_MATH3_VERSION/commons-math3-$COMMONS_MATH3_VERSION.jar +wget http://central.maven.org/maven2/net/sf/jopt-simple/jopt-simple/$JOPT_SIMPLE_VERSION/jopt-simple-$JOPT_SIMPLE_VERSION.jar +wget http://central.maven.org/maven2/org/openjdk/jmh/jmh-core/$JMH_VERSION/jmh-core-$JMH_VERSION.jar +wget http://central.maven.org/maven2/org/openjdk/jmh/jmh-generator-annprocess/$JMH_VERSION/jmh-generator-annprocess-$JMH_VERSION.jar + +tar -cvzf ../$BUNDLE_NAME * + +echo "Created $BUILD_DIR/$BUNDLE_NAME" diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk new file mode 100644 index 00000000000..aeec1b0f9e4 --- /dev/null +++ b/make/test/BuildMicrobenchmark.gmk @@ -0,0 +1,113 @@ +# +# 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. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include SetupJavaCompilers.gmk + +ifeq ($(JMH_CORE_JAR), ) + $(info Error: JMH is missing. Please use configure --with-jmh.) + $(error Cannot continue) +endif + +#### Variables + +MICROBENCHMARK_SRC := $(TOPDIR)/test/micro +MICROBENCHMARK_JAR := $(IMAGES_OUTPUTDIR)/test/micro/benchmarks.jar + +MICROBENCHMARK_OUTPUT := $(SUPPORT_OUTPUTDIR)/test/micro +MICROBENCHMARK_CLASSES := $(MICROBENCHMARK_OUTPUT)/classes +MICROBENCHMARK_JAR_BIN := $(MICROBENCHMARK_OUTPUT)/jar + +JMH_UNPACKED_DIR := $(MICROBENCHMARK_OUTPUT)/jmh_jars +JMH_UNPACKED_JARS_DONE := $(JMH_UNPACKED_DIR)/_unpacked.marker + +# External dependencies +JMH_COMPILE_JARS := $(JMH_CORE_JAR) $(JMH_GENERATOR_JAR) +JMH_RUNTIME_JARS := $(JMH_CORE_JAR) $(JMH_COMMONS_MATH_JAR) $(JMH_JOPT_SIMPLE_JAR) + +MICROBENCHMARK_CLASSPATH := $(call PathList, $(JMH_COMPILE_JARS)) + +### + +# Need double \n to get new lines and no trailing spaces +MICROBENCHMARK_MANIFEST := Build: $(FULL_VERSION)\n\ +\nJMH-Version: $(JMH_VERSION)\n\ +\nName: OpenJDK Microbenchmark Suite + + +#### Compile Targets + +# Building microbenchmark requires the jdk.unsupported and java.management modules, +# and to have sjavac disabled. +$(eval $(call SetupJavaCompiler, MICROBENCHMARK_JAVA_COMPILER, \ + JVM := $(JAVA) --add-modules jdk.unsupported --limit-modules java.management, \ + JAVAC := $(NEW_JAVAC), \ + DISABLE_SJAVAC := true, \ + FLAGS := --upgrade-module-path $(JDK_OUTPUTDIR)/modules --system none $(DISABLE_WARNINGS), \ + SERVER_DIR := $(SJAVAC_SERVER_DIR), \ + SERVER_JVM := $(SJAVAC_SERVER_JAVA), \ +)) + +# Build microbenchmark suite for the current JDK +$(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ + SETUP := MICROBENCHMARK_JAVA_COMPILER, \ + ADD_JAVAC_FLAGS := -cp $(MICROBENCHMARK_CLASSPATH) -Xlint -Werror, \ + SRC := $(MICROBENCHMARK_SRC), \ + BIN := $(MICROBENCHMARK_CLASSES), \ +)) + +$(BUILD_JDK_MICROBENCHMARK): $(JMH_COMPILE_JARS) + +# Unpacking dependencies for inclusion in the benchmark JARs +$(JMH_UNPACKED_JARS_DONE): $(JMH_RUNTIME_JARS) + $(RM) -r $(JMH_UNPACKED_DIR) + $(MKDIR) -p $(JMH_UNPACKED_DIR) + $(foreach jar, $(JMH_RUNTIME_JARS), \ + $$($(UNZIP) -oq $(jar) -d $(JMH_UNPACKED_DIR))) + $(RM) -r $(JMH_UNPACKED_DIR)/META-INF + $(RM) $(JMH_UNPACKED_DIR)/*.xml + $(TOUCH) $@ + +# Create benchmarks JAR file with benchmarks for both the old and new JDK +$(eval $(call SetupJarArchive, BUILD_JDK_JAR, \ + DEPENDENCIES := $(BUILD_JDK_MICROBENCHMARK) $(JMH_UNPACKED_JARS_DONE), \ + SRCS := $(MICROBENCHMARK_CLASSES) $(JMH_UNPACKED_DIR), \ + BIN := $(MICROBENCHMARK_JAR_BIN), \ + SUFFIXES := .*, \ + EXCLUDE_FILES:= _the.BUILD_JDK_MICROBENCHMARK_batch \ + _the.BUILD_JDK_MICROBENCHMARK.vardeps _unpacked.marker, \ + EXTRA_MANIFEST_ATTR := $(MICROBENCHMARK_MANIFEST), \ + JARMAIN := org.openjdk.jmh.Main, \ + JAR := $(MICROBENCHMARK_JAR), \ +)) + +all: $(MICROBENCHMARK_JAR) + +.PHONY: all diff --git a/test/micro/org/openjdk/bench/java/io/BlackholedOutputStream.java b/test/micro/org/openjdk/bench/java/io/BlackholedOutputStream.java new file mode 100644 index 00000000000..970f5b1f2c6 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/BlackholedOutputStream.java @@ -0,0 +1,52 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/io/FileChannelRead.java b/test/micro/org/openjdk/bench/java/io/FileChannelRead.java new file mode 100644 index 00000000000..67714d828f2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/FileChannelRead.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/io/FileChannelWrite.java b/test/micro/org/openjdk/bench/java/io/FileChannelWrite.java new file mode 100644 index 00000000000..51415fee676 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/FileChannelWrite.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/io/FileRead.java b/test/micro/org/openjdk/bench/java/io/FileRead.java new file mode 100644 index 00000000000..7fb828dcf71 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/FileRead.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. + * + * 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/org/openjdk/bench/java/io/FileWrite.java b/test/micro/org/openjdk/bench/java/io/FileWrite.java new file mode 100644 index 00000000000..ea6abf779cf --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/FileWrite.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. + * + * 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/org/openjdk/bench/java/io/ObjectStreamClasses.java b/test/micro/org/openjdk/bench/java/io/ObjectStreamClasses.java new file mode 100644 index 00000000000..75b8f034500 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/ObjectStreamClasses.java @@ -0,0 +1,244 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/io/RandomAccessRead.java b/test/micro/org/openjdk/bench/java/io/RandomAccessRead.java new file mode 100644 index 00000000000..0f3ed1110fb --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/RandomAccessRead.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. + * + * 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/org/openjdk/bench/java/io/RandomAccessWrite.java b/test/micro/org/openjdk/bench/java/io/RandomAccessWrite.java new file mode 100644 index 00000000000..8b4b8216ccb --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/RandomAccessWrite.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. + * + * 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/org/openjdk/bench/java/io/SerializationWriteReplace.java b/test/micro/org/openjdk/bench/java/io/SerializationWriteReplace.java new file mode 100644 index 00000000000..ec5cea2f167 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/SerializationWriteReplace.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. + * + * 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/org/openjdk/bench/java/io/UTF8.java b/test/micro/org/openjdk/bench/java/io/UTF8.java new file mode 100644 index 00000000000..add34b1b8ac --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/UTF8.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. + * + * 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/org/openjdk/bench/java/lang/ArrayCopy.java b/test/micro/org/openjdk/bench/java/lang/ArrayCopy.java new file mode 100644 index 00000000000..b47e2e2deec --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ArrayCopy.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. + * + * 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 java.util.concurrent.TimeUnit; + +/** + * Benchmark measuring System.arraycopy in different ways. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class ArrayCopy { + + private static final byte[] TEST_BYTES = "HTTP/1.0".getBytes(); + private static final char[] TEST_CHARS = new char[46]; + private static final Object[] TEST_OBJECTS = new Object[200]; // Uses a minimum of 160 internal positions for internal copying + + // a length which the compiler cannot prove is a constant + public static int nonConstCharLength = TEST_CHARS.length; + public static int nonConstByteLength = TEST_BYTES.length; + public static int nonConstObjectLength = TEST_OBJECTS.length; + + // Use this array to copy objects in. + public char[] dummyCharArray = new char[TEST_CHARS.length]; + public byte[] dummyByteArray = new byte[TEST_BYTES.length]; + public Object[] dummyObjectArray = new Object[TEST_OBJECTS.length]; + + @Setup + public void setup() { + for (int i = 0; i < TEST_OBJECTS.length; i++) { + TEST_OBJECTS[i] = new Object(); + dummyObjectArray[i] = new Object(); + } + } + + /** + * This test case do the same work as testArrayCopy. We should make sure + * testArrayCopy is equally fast or better. Compare the two and you measure + * the system call versus explicit copy for-loop. + */ + @Benchmark + public void copyLoop() { + for (int j = 0; j < dummyByteArray.length; j++) { + dummyByteArray[j] = TEST_BYTES[j]; + } + } + + /** + * Test that we can optimize away the code since it should not have any side + * effects + */ + @Benchmark + public void copyLoopLocalArray() { + byte[] localDummyByteArray = new byte[TEST_BYTES.length]; + for (int j = 0; j < localDummyByteArray.length; j++) { + localDummyByteArray[j] = TEST_BYTES[j]; + } + } + + /** + * This test case do the same work as testArrayCopy. We should make sure + * testArrayCopy is equally fast or better. Compare the two and you measure + * the system call versus explicit copy for-loop. + *

      + * Uses non-provable constant length. + */ + @Benchmark + public void copyLoopNonConst() { + for (int i = 0; i < nonConstByteLength; i++) { + dummyByteArray[i] = TEST_BYTES[i]; + } + } + + /** + * This test case do the same work as testCopyLoop. We should make sure + * testArrayCopy is equally fast or better. Compare the two and you measure + * the system call versus explicit copy for-loop. + */ + @Benchmark + public void arrayCopy() { + System.arraycopy(TEST_BYTES, 0, dummyByteArray, 0, dummyByteArray.length); + } + + /** + * Test that we can optimize away the code since it should not have any side + * effects + */ + @Benchmark + public void arrayCopyLocalArray() { + byte[] localDummyByteArray = new byte[TEST_BYTES.length]; + System.arraycopy(TEST_BYTES, 0, localDummyByteArray, 0, localDummyByteArray.length); + } + + /** + * This test case do the same work as testCopyLoop. We should make sure + * testArrayCopy is equally fast or better. Compare the two and you measure + * the system call versus explicit copy for-loop. + *

      + * Uses non-provable constant length. + */ + @Benchmark + public void arrayCopyNonConst() { + System.arraycopy(TEST_BYTES, 0, dummyByteArray, 0, nonConstByteLength); + } + + @Benchmark + public void arrayCopyChar() { + System.arraycopy(TEST_CHARS, 0, dummyCharArray, 0, dummyCharArray.length); + } + + @Benchmark + public void arrayCopyCharNonConst() { + System.arraycopy(TEST_CHARS, 0, dummyCharArray, 0, nonConstCharLength); + } + + @Benchmark + public void arrayCopyObject() { + System.arraycopy(TEST_OBJECTS, 0, dummyObjectArray, 0, dummyObjectArray.length); + } + + @Benchmark + public void arrayCopyObjectNonConst() { + System.arraycopy(TEST_OBJECTS, 0, dummyObjectArray, 0, nonConstObjectLength); + } + + /** + * This test copies inside a object array, that is same source array as dest + * array. Copies backwards in the array. + */ + @Benchmark + @OperationsPerInvocation(40) + public void arrayCopyObjectSameArraysBackward() { + for (int i = 0; i < 40; i++) { + System.arraycopy(dummyObjectArray, i, dummyObjectArray, i + 40, 80); + } + } + + /** + * This test copies inside a object array, that is same source array as dest + * array. Copies forward in the array. There is a special version for this + * in JRockit. + */ + @Benchmark + @OperationsPerInvocation(40) + public void arrayCopyObjectSameArraysForward() { + for (int i = 0; i < 40; i++) { + System.arraycopy(dummyObjectArray, i + 40, dummyObjectArray, i, 80); + } + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/ArrayCopyAligned.java b/test/micro/org/openjdk/bench/java/lang/ArrayCopyAligned.java new file mode 100644 index 00000000000..2d540926b3b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ArrayCopyAligned.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. + * + * 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/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.java new file mode 100644 index 00000000000..045ccc5b019 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedBoth.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. + * + * 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/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.java new file mode 100644 index 00000000000..e6c1c3a20dc --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedDst.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. + * + * 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/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.java new file mode 100644 index 00000000000..3fa9538de67 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ArrayCopyUnalignedSrc.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. + * + * 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/org/openjdk/bench/java/lang/ClassForName.java b/test/micro/org/openjdk/bench/java/lang/ClassForName.java new file mode 100644 index 00000000000..58867a5e672 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ClassForName.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. + * + * 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/org/openjdk/bench/java/lang/Clone.java b/test/micro/org/openjdk/bench/java/lang/Clone.java new file mode 100644 index 00000000000..7203a7d692a --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/Clone.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. + * + * 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/org/openjdk/bench/java/lang/FloatingDecimal.java b/test/micro/org/openjdk/bench/java/lang/FloatingDecimal.java new file mode 100644 index 00000000000..d43d2b79e87 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/FloatingDecimal.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. + * + * 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/org/openjdk/bench/java/lang/GetStackTrace.java b/test/micro/org/openjdk/bench/java/lang/GetStackTrace.java new file mode 100644 index 00000000000..0b3a57d7afc --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/GetStackTrace.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/Integers.java b/test/micro/org/openjdk/bench/java/lang/Integers.java new file mode 100644 index 00000000000..c8fbc22d56f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/Integers.java @@ -0,0 +1,66 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/Longs.java b/test/micro/org/openjdk/bench/java/lang/Longs.java new file mode 100644 index 00000000000..84f765ff3c2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/Longs.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. + * + * 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/org/openjdk/bench/java/lang/NewInstance.java b/test/micro/org/openjdk/bench/java/lang/NewInstance.java new file mode 100644 index 00000000000..f1d062e8067 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/NewInstance.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. + * + * 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/org/openjdk/bench/java/lang/ObjectHashCode.java b/test/micro/org/openjdk/bench/java/lang/ObjectHashCode.java new file mode 100644 index 00000000000..b23b7b3a7f8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ObjectHashCode.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. + * + * 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/org/openjdk/bench/java/lang/StringBuffers.java b/test/micro/org/openjdk/bench/java/lang/StringBuffers.java new file mode 100644 index 00000000000..016c930e908 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringBuffers.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. + * + * 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/org/openjdk/bench/java/lang/StringBuilders.java b/test/micro/org/openjdk/bench/java/lang/StringBuilders.java new file mode 100644 index 00000000000..c7b810a75ff --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringBuilders.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. + * + * 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/org/openjdk/bench/java/lang/StringConcat.java b/test/micro/org/openjdk/bench/java/lang/StringConcat.java new file mode 100644 index 00000000000..c199dcb8c71 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringConcat.java @@ -0,0 +1,100 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/StringHashCode.java b/test/micro/org/openjdk/bench/java/lang/StringHashCode.java new file mode 100644 index 00000000000..e00cdb4b050 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringHashCode.java @@ -0,0 +1,69 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/StringHttp.java b/test/micro/org/openjdk/bench/java/lang/StringHttp.java new file mode 100644 index 00000000000..90ce4a10cba --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringHttp.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. + * + * 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/org/openjdk/bench/java/lang/StringIndexOf.java b/test/micro/org/openjdk/bench/java/lang/StringIndexOf.java new file mode 100644 index 00000000000..572484319db --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringIndexOf.java @@ -0,0 +1,138 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/StringOther.java b/test/micro/org/openjdk/bench/java/lang/StringOther.java new file mode 100644 index 00000000000..b81220aaacb --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringOther.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. + * + * 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/org/openjdk/bench/java/lang/StringUpperLower.java b/test/micro/org/openjdk/bench/java/lang/StringUpperLower.java new file mode 100644 index 00000000000..b19fd05e644 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringUpperLower.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. + * + * 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/org/openjdk/bench/java/lang/Systems.java b/test/micro/org/openjdk/bench/java/lang/Systems.java new file mode 100644 index 00000000000..b8f6c65d12f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/Systems.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. + * + * 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/org/openjdk/bench/java/lang/ThreadStartJoin.java b/test/micro/org/openjdk/bench/java/lang/ThreadStartJoin.java new file mode 100644 index 00000000000..5a28d58181f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ThreadStartJoin.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. + * + * 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/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java new file mode 100644 index 00000000000..8a7fed446f2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTarget.java @@ -0,0 +1,208 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.java new file mode 100644 index 00000000000..eab80d59655 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteSetTargetSelf.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. + * + * 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/org/openjdk/bench/java/lang/invoke/CallSiteStable.java b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteStable.java new file mode 100644 index 00000000000..8087a4ec34c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/CallSiteStable.java @@ -0,0 +1,165 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/LookupAcquire.java b/test/micro/org/openjdk/bench/java/lang/invoke/LookupAcquire.java new file mode 100644 index 00000000000..c26f305c6e2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LookupAcquire.java @@ -0,0 +1,94 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java b/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.java new file mode 100644 index 00000000000..906dc35c8a0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefaultFind.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. + * + * 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/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java b/test/micro/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java new file mode 100644 index 00000000000..71aa6a649ea --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LookupPublicFind.java @@ -0,0 +1,106 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.java new file mode 100644 index 00000000000..a555e2f8d87 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsCollector.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.java new file mode 100644 index 00000000000..d78c895d044 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsSpreader.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.java new file mode 100644 index 00000000000..9ee5bf7bc70 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleAsVarargsCollector.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.java new file mode 100644 index 00000000000..a6cfc123db3 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBasicInvoke.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.java new file mode 100644 index 00000000000..791a80bf24f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToBinding.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.java new file mode 100644 index 00000000000..c079a5216ba --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleBindToCurry.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.java new file mode 100644 index 00000000000..0dab3414d1d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertBoxing.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.java new file mode 100644 index 00000000000..869ef6bafc0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertCast.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.java new file mode 100644 index 00000000000..14e0c87b967 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnPrimitive.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.java new file mode 100644 index 00000000000..40a334eacc7 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnReference.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.java new file mode 100644 index 00000000000..16e92a74465 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertReturnVoid.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.java new file mode 100644 index 00000000000..b8545fd0d49 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertUnboxing.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.java new file mode 100644 index 00000000000..69821c49b86 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleConvertWidening.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java new file mode 100644 index 00000000000..f06452ebe2b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleInvokeWithArgs.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.java new file mode 100644 index 00000000000..a4b84f4d094 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesAsIFInstance.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.java new file mode 100644 index 00000000000..29481a35ef1 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandleProxiesSuppl.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.java new file mode 100644 index 00000000000..0b18d57f453 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementGetter.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.java new file mode 100644 index 00000000000..f25dbafcde9 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesArrayElementSetter.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.java new file mode 100644 index 00000000000..0b5d9190df8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesCatchException.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. + * + * 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 + * - 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/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.java new file mode 100644 index 00000000000..492a4c3060e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesConstant.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.java new file mode 100644 index 00000000000..debc2e4d455 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesDropArguments.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.java new file mode 100644 index 00000000000..8def118bc84 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesExactInvoker.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.java new file mode 100644 index 00000000000..81414738ff7 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterArgs.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.java new file mode 100644 index 00000000000..71d37c0bf4e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFilterReturn.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.java new file mode 100644 index 00000000000..7e6d1b9a498 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesFoldArguments.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.java new file mode 100644 index 00000000000..d9c78a029a2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesGuardWithTest.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.java new file mode 100644 index 00000000000..a41986115f6 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesIdentity.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.java new file mode 100644 index 00000000000..a6b23bc4fae --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInsertArguments.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.java new file mode 100644 index 00000000000..c806fd2b76e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesInvoker.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.java new file mode 100644 index 00000000000..9e6886934b8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesPermuteArguments.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.java new file mode 100644 index 00000000000..8677d7d0b5f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesSpreadInvoker.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java new file mode 100644 index 00000000000..08b36af97c0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodHandlesThrowException.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.java new file mode 100644 index 00000000000..90ea2735a93 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAcquire.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.java new file mode 100644 index 00000000000..0a0bfc18975 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeAppendParams.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java new file mode 100644 index 00000000000..245b66402fe --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeParam.java @@ -0,0 +1,66 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java new file mode 100644 index 00000000000..d9f6881010e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeChangeReturn.java @@ -0,0 +1,66 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.java new file mode 100644 index 00000000000..ee5f1d40b44 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeDropParams.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.java new file mode 100644 index 00000000000..4a6277617ce --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeGenerify.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. + * + * 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/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.java new file mode 100644 index 00000000000..75476e0547f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/MethodTypeInsertParams.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. + * + * 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/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java b/test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.java new file mode 100644 index 00000000000..815617c6e8e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointAdhoc.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. + * + * 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/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java b/test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.java new file mode 100644 index 00000000000..c32807ffb14 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/invoke/SwitchPointGuard.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. + * + * 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/org/openjdk/bench/java/lang/reflect/Clazz.java b/test/micro/org/openjdk/bench/java/lang/reflect/Clazz.java new file mode 100644 index 00000000000..ce7b50a75dd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/reflect/Clazz.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. + * + * 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 java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class Clazz { + + /** + * Get constructor for this class through reflection + * + * @return + * @throws NoSuchMethodException + */ + @Benchmark + public Constructor getConstructor() throws NoSuchMethodException { + return Clazz.class.getConstructor(); + } + + /** + * Get constructor for the String class through reflection, forcing full + * security check + * + * @return + * @throws NoSuchMethodException + */ + @Benchmark + public Constructor getConstructorDifferentClassLoader() throws NoSuchMethodException { + return String.class.getConstructor(); + } + + /** + * Get the toString method through reflection on Clazz + * + * @return + */ + @Benchmark + public Method getMethod() throws NoSuchMethodException { + return Clazz.class.getMethod("toString"); + } + + /** + * Get the toString method through reflection on String, forcing full + * security check + * + * @return + * @throws NoSuchMethodException + */ + @Benchmark + public Method getMethodDifferentClassLoader() throws NoSuchMethodException { + return String.class.getMethod("toString"); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/reflect/ClazzWithSecurityManager.java b/test/micro/org/openjdk/bench/java/lang/reflect/ClazzWithSecurityManager.java new file mode 100644 index 00000000000..0d6f92c4ecd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/reflect/ClazzWithSecurityManager.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. + * + * 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 java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; +import java.security.Policy; +import java.security.URIParameter; + +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** + * Reflection benchmark + * + * @author sfriberg + */ +@State(Scope.Benchmark) +public class ClazzWithSecurityManager extends Clazz { + + @Setup + public void setup() throws IOException, NoSuchAlgorithmException, URISyntaxException { + URI policyFile = ClazzWithSecurityManager.class.getResource("/jmh-security.policy").toURI(); + Policy.setPolicy(Policy.getInstance("JavaPolicy", new URIParameter(policyFile))); + System.setSecurityManager(new SecurityManager()); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/reflect/MethodInvoke.java b/test/micro/org/openjdk/bench/java/lang/reflect/MethodInvoke.java new file mode 100644 index 00000000000..a907af958e4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/reflect/MethodInvoke.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. + * + * 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/org/openjdk/bench/java/math/BigDecimals.java b/test/micro/org/openjdk/bench/java/math/BigDecimals.java new file mode 100644 index 00000000000..23006abfdca --- /dev/null +++ b/test/micro/org/openjdk/bench/java/math/BigDecimals.java @@ -0,0 +1,226 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/math/BigIntegers.java b/test/micro/org/openjdk/bench/java/math/BigIntegers.java new file mode 100644 index 00000000000..29c6facea7b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/math/BigIntegers.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. + * + * 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/org/openjdk/bench/java/net/DatagramSocketTest.java b/test/micro/org/openjdk/bench/java/net/DatagramSocketTest.java new file mode 100644 index 00000000000..0cb8a85ebe4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/DatagramSocketTest.java @@ -0,0 +1,75 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/net/SocketChannelReadWrite.java b/test/micro/org/openjdk/bench/java/net/SocketChannelReadWrite.java new file mode 100644 index 00000000000..3f3d1a2d279 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/SocketChannelReadWrite.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. + * + * 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/org/openjdk/bench/java/net/SocketReadWrite.java b/test/micro/org/openjdk/bench/java/net/SocketReadWrite.java new file mode 100644 index 00000000000..73942b138fe --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/SocketReadWrite.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. + * + * 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/org/openjdk/bench/java/net/SocketStreaming.java b/test/micro/org/openjdk/bench/java/net/SocketStreaming.java new file mode 100644 index 00000000000..c7ca017896b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/SocketStreaming.java @@ -0,0 +1,253 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/net/URLEncodeDecode.java b/test/micro/org/openjdk/bench/java/net/URLEncodeDecode.java new file mode 100644 index 00000000000..becbf996455 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/URLEncodeDecode.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/nio/ByteBuffers.java b/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java new file mode 100644 index 00000000000..c9e28b0e3cd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/ByteBuffers.java @@ -0,0 +1,336 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/nio/CharsetEncodeDecode.java b/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.java new file mode 100644 index 00000000000..7ec85bdaea4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/CharsetEncodeDecode.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. + * + * 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/org/openjdk/bench/java/security/DoPrivileged.java b/test/micro/org/openjdk/bench/java/security/DoPrivileged.java new file mode 100644 index 00000000000..49a4a9eb6d8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/security/DoPrivileged.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. + * + * 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/org/openjdk/bench/java/security/MessageDigests.java b/test/micro/org/openjdk/bench/java/security/MessageDigests.java new file mode 100644 index 00000000000..33dc93f8870 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/security/MessageDigests.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. + * + * 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/org/openjdk/bench/java/util/ArraysEquals.java b/test/micro/org/openjdk/bench/java/util/ArraysEquals.java new file mode 100644 index 00000000000..b3500a35b33 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/ArraysEquals.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. + * + * 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/org/openjdk/bench/java/util/Dates.java b/test/micro/org/openjdk/bench/java/util/Dates.java new file mode 100644 index 00000000000..242217e4d33 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/Dates.java @@ -0,0 +1,60 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/GregorianCalendars.java b/test/micro/org/openjdk/bench/java/util/GregorianCalendars.java new file mode 100644 index 00000000000..776af6bbfed --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/GregorianCalendars.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/RandomNext.java b/test/micro/org/openjdk/bench/java/util/RandomNext.java new file mode 100644 index 00000000000..342e31c7f92 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/RandomNext.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. + * + * 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/org/openjdk/bench/java/util/ZipFind.java b/test/micro/org/openjdk/bench/java/util/ZipFind.java new file mode 100644 index 00000000000..77ceb451f93 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/ZipFind.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. + * + * 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/org/openjdk/bench/java/util/concurrent/Atomic.java b/test/micro/org/openjdk/bench/java/util/concurrent/Atomic.java new file mode 100644 index 00000000000..4e60f52574b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Atomic.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java b/test/micro/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.java new file mode 100644 index 00000000000..9c5fa347b7c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/AtomicIntegerUpdateAndGet.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. + * + * 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/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java new file mode 100644 index 00000000000..38be65897ad --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolForking.java @@ -0,0 +1,178 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java new file mode 100644 index 00000000000..8254d04966e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolRawCallable.java @@ -0,0 +1,154 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.java new file mode 100644 index 00000000000..d5bf8169839 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoQueued.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. + * + * 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/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.java new file mode 100644 index 00000000000..c419dda4e1e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdAutoSurplus.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. + * + * 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/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.java new file mode 100644 index 00000000000..b3e20dfdc15 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ForkJoinPoolThresholdStatic.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. + * + * 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/org/openjdk/bench/java/util/concurrent/Locks.java b/test/micro/org/openjdk/bench/java/util/concurrent/Locks.java new file mode 100644 index 00000000000..8060a44e76f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Locks.java @@ -0,0 +1,232 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/concurrent/Maps.java b/test/micro/org/openjdk/bench/java/util/concurrent/Maps.java new file mode 100644 index 00000000000..de4c71880ea --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Maps.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. + * + * 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/org/openjdk/bench/java/util/concurrent/Problem.java b/test/micro/org/openjdk/bench/java/util/concurrent/Problem.java new file mode 100644 index 00000000000..8322419dd87 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Problem.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. + * + * 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/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java b/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.java new file mode 100644 index 00000000000..94f37ab2dd1 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ProducerConsumer.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. + * + * 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/org/openjdk/bench/java/util/concurrent/Queues.java b/test/micro/org/openjdk/bench/java/util/concurrent/Queues.java new file mode 100644 index 00000000000..ea2c8b4bff6 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/Queues.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. + * + * 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/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java b/test/micro/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.java new file mode 100644 index 00000000000..a309a3b204b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/ThreadLocalRandomNextInt.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. + * + * 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/org/openjdk/bench/java/util/logging/LogRecord.java b/test/micro/org/openjdk/bench/java/util/logging/LogRecord.java new file mode 100644 index 00000000000..3f9fb6e579b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/logging/LogRecord.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. + * + * 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/org/openjdk/bench/java/util/stream/AllMatcher.java b/test/micro/org/openjdk/bench/java/util/stream/AllMatcher.java new file mode 100644 index 00000000000..27e2dd003af --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/AllMatcher.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. + * + * 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/org/openjdk/bench/java/util/stream/AnyMatcher.java b/test/micro/org/openjdk/bench/java/util/stream/AnyMatcher.java new file mode 100644 index 00000000000..91d6ce40646 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/AnyMatcher.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. + * + * 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/org/openjdk/bench/java/util/stream/Decomposition.java b/test/micro/org/openjdk/bench/java/util/stream/Decomposition.java new file mode 100644 index 00000000000..999135c142d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/Decomposition.java @@ -0,0 +1,112 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/NoneMatcher.java b/test/micro/org/openjdk/bench/java/util/stream/NoneMatcher.java new file mode 100644 index 00000000000..b5f7fd36fd5 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/NoneMatcher.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. + * + * 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/org/openjdk/bench/java/util/stream/Reducers.java b/test/micro/org/openjdk/bench/java/util/stream/Reducers.java new file mode 100644 index 00000000000..fd31cecc023 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/Reducers.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java b/test/micro/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java new file mode 100644 index 00000000000..36503235033 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/LongAccumulator.java @@ -0,0 +1,45 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java new file mode 100644 index 00000000000..c941c542d65 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatch.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java new file mode 100644 index 00000000000..0356226c13f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AllMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java new file mode 100644 index 00000000000..d4fefd266db --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatch.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java new file mode 100644 index 00000000000..9e160cc7fc9 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/AnyMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/Filter.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Filter.java new file mode 100644 index 00000000000..eef01587417 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Filter.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java new file mode 100644 index 00000000000..26d14dc91b0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindAny.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java new file mode 100644 index 00000000000..2ff9a223751 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/FindFirst.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/ForEach.java new file mode 100644 index 00000000000..2804649abc2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/ForEach.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/Limit.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Limit.java new file mode 100644 index 00000000000..af9c5f2f352 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Limit.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/Map.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Map.java new file mode 100644 index 00000000000..e043b9478ae --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Map.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java new file mode 100644 index 00000000000..9f3bac716dc --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatch.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java new file mode 100644 index 00000000000..8bf697982fa --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/NoneMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java new file mode 100644 index 00000000000..ed7264789d5 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Reduce.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.java new file mode 100644 index 00000000000..11d2261b3f1 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/ReduceBase.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Sorted.java new file mode 100644 index 00000000000..7aafd19fbe2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/Sorted.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.java new file mode 100644 index 00000000000..4f5e87dbeb0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/SortedUnique.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.java new file mode 100644 index 00000000000..12cf447d7d1 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/ref/UniqueElements.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java new file mode 100644 index 00000000000..6bf21a07622 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatch.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java new file mode 100644 index 00000000000..d5fd8d928c4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AllMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java new file mode 100644 index 00000000000..483a7f9d81d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatch.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java new file mode 100644 index 00000000000..a80cde61ac8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/AnyMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/Filter.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Filter.java new file mode 100644 index 00000000000..b939d49dd04 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Filter.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/FindAny.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/FindAny.java new file mode 100644 index 00000000000..c7e08239c00 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/FindAny.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java new file mode 100644 index 00000000000..f812e1fbe16 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/FindFirst.java @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/ForEach.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/ForEach.java new file mode 100644 index 00000000000..e4b6a40c421 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/ForEach.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/Limit.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Limit.java new file mode 100644 index 00000000000..621944acab1 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Limit.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/Map.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Map.java new file mode 100644 index 00000000000..bb7954a55dd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Map.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java new file mode 100644 index 00000000000..f8d4ad5eba4 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatch.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java new file mode 100644 index 00000000000..4d3d4fef4ec --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/NoneMatchShort.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/Reduce.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Reduce.java new file mode 100644 index 00000000000..841e7defb4e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Reduce.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java new file mode 100644 index 00000000000..be83c070463 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/ReduceBase.java @@ -0,0 +1,125 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/Sorted.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Sorted.java new file mode 100644 index 00000000000..7d39201a7dd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/Sorted.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.java new file mode 100644 index 00000000000..bd09306e719 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/SortedUnique.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. + * + * 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/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java b/test/micro/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.java new file mode 100644 index 00000000000..6d7dc57b286 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/ops/value/UniqueElements.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. + * + * 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/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.java new file mode 100644 index 00000000000..7ea4732592f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineParMultiple.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. + * + * 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/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.java new file mode 100644 index 00000000000..debe7ef7614 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSeqMultiple.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. + * + * 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/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java new file mode 100644 index 00000000000..e0b51350bc3 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/pipeline/PipelineSetup.java @@ -0,0 +1,186 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/pipeline/Terminal.java b/test/micro/org/openjdk/bench/java/util/stream/pipeline/Terminal.java new file mode 100644 index 00000000000..4bf715e10ed --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/pipeline/Terminal.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/DataProviders.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DataProviders.java new file mode 100644 index 00000000000..326c26c20d4 --- /dev/null +++ b/test/micro/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/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.java new file mode 100644 index 00000000000..aa3c0879660 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Bulk.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.java new file mode 100644 index 00000000000..30145f8ed17 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/DictionaryProblem.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Lambda.java new file mode 100644 index 00000000000..1cd7618757b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java new file mode 100644 index 00000000000..9906d07aae7 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/DictionaryWordValue/Xtras.java @@ -0,0 +1,32 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java new file mode 100644 index 00000000000..1bde5f9cc92 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Bulk.java @@ -0,0 +1,132 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java new file mode 100644 index 00000000000..4a4adbd412a --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/IntegerDuplicateProblem.java @@ -0,0 +1,45 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.java new file mode 100644 index 00000000000..898bec1492e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerDuplicate/Lambda.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Bulk.java new file mode 100644 index 00000000000..9946f1e1ac0 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java new file mode 100644 index 00000000000..85b9215e182 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/IntegerMaxProblem.java @@ -0,0 +1,45 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.java new file mode 100644 index 00000000000..f6bcf105250 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Lambda.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.java new file mode 100644 index 00000000000..b2663ed4b8c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerMax/Xtras.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java new file mode 100644 index 00000000000..32982b51c8a --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Bulk.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java new file mode 100644 index 00000000000..2b7beecb71c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/IntegerSumProblem.java @@ -0,0 +1,45 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java new file mode 100644 index 00000000000..ef6aa059552 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Lambda.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/Xtras.java new file mode 100644 index 00000000000..6f9494a0208 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/IntegerSum/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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/Bulk.java new file mode 100644 index 00000000000..a9713578177 --- /dev/null +++ b/test/micro/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/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PhoneCode/PhoneCodeProblem.java new file mode 100644 index 00000000000..4e5d492901a --- /dev/null +++ b/test/micro/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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.java new file mode 100644 index 00000000000..ad37e5aec98 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/PrimesProblem.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java new file mode 100644 index 00000000000..68cabddad8c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Bulk.java @@ -0,0 +1,147 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.java new file mode 100644 index 00000000000..bc3b4043d5c --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Lambda.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.java new file mode 100644 index 00000000000..fd54e4b20d2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t100/Xtras.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java new file mode 100644 index 00000000000..fc00fa5b582 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Bulk.java @@ -0,0 +1,147 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.java new file mode 100644 index 00000000000..387feaa37b3 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Lambda.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.java new file mode 100644 index 00000000000..219182d3173 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesFilter/t10000/Xtras.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.java new file mode 100644 index 00000000000..dd32f7743ef --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/Bulk.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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java new file mode 100644 index 00000000000..3b03ee7b4b7 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/stream/tasks/PrimesSieve/PrimesSieveProblem.java @@ -0,0 +1,44 @@ +/* + * 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. + * + * 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/org/openjdk/bench/java/util/stream/tasks/README b/test/micro/org/openjdk/bench/java/util/stream/tasks/README new file mode 100644 index 00000000000..df03bd4abbe --- /dev/null +++ b/test/micro/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. +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/org/openjdk/bench/javax/crypto/AES.java b/test/micro/org/openjdk/bench/javax/crypto/AES.java new file mode 100644 index 00000000000..e22f28bc74f --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/crypto/AES.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. + * + * 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/org/openjdk/bench/javax/crypto/Crypto.java b/test/micro/org/openjdk/bench/javax/crypto/Crypto.java new file mode 100644 index 00000000000..98f52187017 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/crypto/Crypto.java @@ -0,0 +1,112 @@ +/* + * 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. + * + * 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/org/openjdk/bench/javax/tools/Javac.java b/test/micro/org/openjdk/bench/javax/tools/Javac.java new file mode 100644 index 00000000000..fb548092a39 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/tools/Javac.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. + * + * 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/org/openjdk/bench/javax/xml/AbstractXMLMicro.java b/test/micro/org/openjdk/bench/javax/xml/AbstractXMLMicro.java new file mode 100644 index 00000000000..bac501d9890 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/xml/AbstractXMLMicro.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. + * + * 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/org/openjdk/bench/javax/xml/DOM.java b/test/micro/org/openjdk/bench/javax/xml/DOM.java new file mode 100644 index 00000000000..d5fc19c7a66 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/xml/DOM.java @@ -0,0 +1,158 @@ +/* + * 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. + * + * 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/org/openjdk/bench/javax/xml/SAXUsingJDK.java b/test/micro/org/openjdk/bench/javax/xml/SAXUsingJDK.java new file mode 100644 index 00000000000..0f51b7e37be --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/xml/SAXUsingJDK.java @@ -0,0 +1,53 @@ +/* + * 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. + * + * 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/org/openjdk/bench/javax/xml/STAX.java b/test/micro/org/openjdk/bench/javax/xml/STAX.java new file mode 100644 index 00000000000..748184e8b09 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/xml/STAX.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. + * + * 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/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java b/test/micro/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.java new file mode 100644 index 00000000000..c47faf9586b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/ArrayBoundCheckRemoval.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. + * + * 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/org/openjdk/bench/vm/compiler/ArrayClear.java b/test/micro/org/openjdk/bench/vm/compiler/ArrayClear.java new file mode 100644 index 00000000000..e1055b03b2b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/ArrayClear.java @@ -0,0 +1,60 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java b/test/micro/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java new file mode 100644 index 00000000000..61671af19d0 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/ArrayStoreCheck.java @@ -0,0 +1,193 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/CopyLoop.java b/test/micro/org/openjdk/bench/vm/compiler/CopyLoop.java new file mode 100644 index 00000000000..5ac09e1205d --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/CopyLoop.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. + * + * 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/org/openjdk/bench/vm/compiler/DivRem.java b/test/micro/org/openjdk/bench/vm/compiler/DivRem.java new file mode 100644 index 00000000000..514c8f29c70 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/DivRem.java @@ -0,0 +1,217 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/Explosion.java b/test/micro/org/openjdk/bench/vm/compiler/Explosion.java new file mode 100644 index 00000000000..6c9d1301ead --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/Explosion.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. + * + * 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/org/openjdk/bench/vm/compiler/InnerClassNullRef.java b/test/micro/org/openjdk/bench/vm/compiler/InnerClassNullRef.java new file mode 100644 index 00000000000..ac05f0b4594 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/InnerClassNullRef.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. + * + * 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/org/openjdk/bench/vm/compiler/InterfaceCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java new file mode 100644 index 00000000000..60b705afbcf --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java @@ -0,0 +1,287 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/Multiplication.java b/test/micro/org/openjdk/bench/vm/compiler/Multiplication.java new file mode 100644 index 00000000000..57e55fd2430 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/Multiplication.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. + * + * 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/org/openjdk/bench/vm/compiler/PostAllocationStores.java b/test/micro/org/openjdk/bench/vm/compiler/PostAllocationStores.java new file mode 100644 index 00000000000..32d797b7886 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/PostAllocationStores.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. + * + * 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/org/openjdk/bench/vm/compiler/SpillCode.java b/test/micro/org/openjdk/bench/vm/compiler/SpillCode.java new file mode 100644 index 00000000000..feef45ad45f --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/SpillCode.java @@ -0,0 +1,204 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/StoreAfterStore.java b/test/micro/org/openjdk/bench/vm/compiler/StoreAfterStore.java new file mode 100644 index 00000000000..e462b5c559c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/StoreAfterStore.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. + * + * 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/org/openjdk/bench/vm/compiler/Straighten.java b/test/micro/org/openjdk/bench/vm/compiler/Straighten.java new file mode 100644 index 00000000000..46a21b305c4 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/Straighten.java @@ -0,0 +1,248 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/compiler/WriteBarrier.java b/test/micro/org/openjdk/bench/vm/compiler/WriteBarrier.java new file mode 100644 index 00000000000..9916b396531 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/WriteBarrier.java @@ -0,0 +1,162 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/gc/Alloc.java b/test/micro/org/openjdk/bench/vm/gc/Alloc.java new file mode 100644 index 00000000000..300afd48d4c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/Alloc.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. + * + * 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/org/openjdk/bench/vm/lambda/capture/Capture0.java b/test/micro/org/openjdk/bench/vm/lambda/capture/Capture0.java new file mode 100644 index 00000000000..c496f64de1f --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/capture/Capture0.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. + * + * 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/org/openjdk/bench/vm/lambda/capture/Capture2.java b/test/micro/org/openjdk/bench/vm/lambda/capture/Capture2.java new file mode 100644 index 00000000000..2fd6bbd998a --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/capture/Capture2.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. + * + * 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/org/openjdk/bench/vm/lambda/capture/CaptureMR.java b/test/micro/org/openjdk/bench/vm/lambda/capture/CaptureMR.java new file mode 100644 index 00000000000..378b01a40bc --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/capture/CaptureMR.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. + * + * 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/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java b/test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java new file mode 100644 index 00000000000..c0e160b82fc --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface0.java @@ -0,0 +1,35 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java b/test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java new file mode 100644 index 00000000000..f4fbb582c4f --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/capture/FunctionalInterface1.java @@ -0,0 +1,35 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java new file mode 100644 index 00000000000..174eeca8030 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap0.java @@ -0,0 +1,162 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java new file mode 100644 index 00000000000..50beb907586 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap1.java @@ -0,0 +1,162 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java new file mode 100644 index 00000000000..7cd7460366b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainAnonymCap4.java @@ -0,0 +1,162 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainBase.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainBase.java new file mode 100644 index 00000000000..206b17ffa0c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainBase.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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java new file mode 100644 index 00000000000..91b8659944e --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap0.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java new file mode 100644 index 00000000000..623d03ed134 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap1.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java new file mode 100644 index 00000000000..19e6597893c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainLambdaCap4.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java new file mode 100644 index 00000000000..1b0b9e92a6b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefBound.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java new file mode 100644 index 00000000000..2b37640a24c --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/ChainMrefUnbound.java @@ -0,0 +1,117 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/Level.java b/test/micro/org/openjdk/bench/vm/lambda/chain/Level.java new file mode 100644 index 00000000000..4faac929eb9 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/Level.java @@ -0,0 +1,35 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/chain/TopLevel.java b/test/micro/org/openjdk/bench/vm/lambda/chain/TopLevel.java new file mode 100644 index 00000000000..c2faef6fdc8 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/chain/TopLevel.java @@ -0,0 +1,38 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/AckermannI.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannI.java new file mode 100644 index 00000000000..dd0a78a9cb4 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannI.java @@ -0,0 +1,112 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/AckermannL.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannL.java new file mode 100644 index 00000000000..b0079400da3 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/AckermannL.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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/Function0.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/Function0.java new file mode 100644 index 00000000000..fd1f7dcbb80 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/Function0.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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/Function1.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/Function1.java new file mode 100644 index 00000000000..26e810d525b --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/Function1.java @@ -0,0 +1,350 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/Morph0.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph0.java new file mode 100644 index 00000000000..7ddda3afbb7 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph0.java @@ -0,0 +1,257 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/Morph1.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph1.java new file mode 100644 index 00000000000..e323aae0b2d --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph1.java @@ -0,0 +1,157 @@ +/* + * 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. + * + * 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/org/openjdk/bench/vm/lambda/invoke/Morph2.java b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph2.java new file mode 100644 index 00000000000..4b6ec3380a7 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lambda/invoke/Morph2.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. + * + * 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/org/openjdk/bench/vm/lang/InstanceOf.java b/test/micro/org/openjdk/bench/vm/lang/InstanceOf.java new file mode 100644 index 00000000000..7e031d572cb --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lang/InstanceOf.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. + * + * 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/org/openjdk/bench/vm/lang/LockUnlock.java b/test/micro/org/openjdk/bench/vm/lang/LockUnlock.java new file mode 100644 index 00000000000..efc69d233a6 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lang/LockUnlock.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. + * + * 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/org/openjdk/bench/vm/lang/Throw.java b/test/micro/org/openjdk/bench/vm/lang/Throw.java new file mode 100644 index 00000000000..86313bc2da6 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/lang/Throw.java @@ -0,0 +1,135 @@ +/* + * 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. + * + * 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(); + } +}