Tag: microbenchmark

java缓存方法的结果

我使用 JMH来指定操作的复杂性。 如果您从未与JMH合作过,请不要担心。 JMH将多次启动estimateOperation方法,然后获得平均时间。 问题:[narrow]这个程序每次都会计算Math.cbrt(Integer.MAX_VALUE)吗? 或者它只计算一次然后返回缓存结果? @GenerateMicroBenchmark public void estimateOperation() { calculate(); } public int calculate() { return Math.cbrt(Integer.MAX_VALUE); } 问题:[broad]: JVM是否会缓存方法的结果?

具有恒定长度的System.arraycopy

我正在玩JMH( http://openjdk.java.net/projects/code-tools/jmh/ ),我偶然发现了一个奇怪的结果。 我正在对数组的浅层副本进行基准测试,我可以观察到预期的结果(循环遍历数组是一个坏主意,并且#clone() , System#arraycopy()和Arrays#copyOf()之间没有显着差异Arrays#copyOf() ,性能方面)。 当数组的长度是硬编码时System#arraycopy()减慢四分之一……等等,什么? 怎么会这么慢? 有没有人知道可能是什么原因? 结果(吞吐量): # JMH 1.11 (released 17 days ago) # VM version: JDK 1.8.0_05, VM 25.5-b02 # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/bin/java # VM options: -Dfile.encoding=UTF-8 -Duser.country=FR -Duser.language=fr -Duser.variant # Warmup: 20 iterations, 1 s each # Measurement: 20 iterations, 1 s each # Timeout: 10 min per […]

对于小型数组,为什么Arrays.copyOf比System.arraycopy快2倍?

我最近玩了一些基准测试,发现了非常有趣的结果,我现在无法解释。 这是基准: @BenchmarkMode(Mode.Throughput) @Fork(1) @State(Scope.Thread) @Warmup(iterations = 10, time = 1, batchSize = 1000) @Measurement(iterations = 10, time = 1, batchSize = 1000) public class ArrayCopy { @Param({“1″,”5″,”10″,”100”, “1000”}) private int size; private int[] ar; @Setup public void setup() { ar = new int[size]; for (int i = 0; i < size; i++) { ar[i] […]

什么可以解释写入堆位置引用的巨大性能损失?

在研究分代垃圾收集器对应用程序性能的微妙后果时,我已经在一个非常基本的操作 – 一个简单的写入堆位置 – 的性能方面遇到了相当惊人的差异,关于所写的值是原始值还是引用。 微基准 @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 1, time = 1) @Measurement(iterations = 3, time = 1) @State(Scope.Thread) @Threads(1) @Fork(2) public class Writing { static final int TARGET_SIZE = 1024; static final int[] primitiveArray = new int[TARGET_SIZE]; static final Object[] referenceArray = new Object[TARGET_SIZE]; int val = 1; @GenerateMicroBenchmark public void fillPrimitiveArray() […]

了解-XX:+ PrintCompilation的输出

我在Java列表迭代代码上运行一些微基准测试。 我使用了-XX:+ PrintCompilation和-verbose:gc标志来确保在运行定时时后台没有发生任何事情。 但是,我在输出中看到了一些我无法理解的东西。 这是代码,我正在运行基准测试: import java.util.ArrayList; import java.util.List; public class PerformantIteration { private static int theSum = 0; public static void main(String[] args) { System.out.println(“Starting microbenchmark on iterating over collections with a call to size() in each iteration”); List nums = new ArrayList(); for(int i=0; i<50000; i++) { nums.add(i); } System.out.println("Warming up …"); //warmup… […]

第一次Java循环运行时,为什么?

在对Solaris SPARC盒子上的一些Java代码进行基准测试时,我注意到我第一次调用基准测试函数时,它运行得很慢(10倍差异): 首先| 1 | 25295.979毫秒 第二| 1 | 2256.990毫秒 第三| 1 | 2250.575毫秒 为什么是这样? 我怀疑是JIT编译器,有没有办法validation这个? 编辑:根据一些答案,我想澄清一下,这段代码是最简单的测试案例,我可以找到展示这种行为。 所以我的目标不是让它快速运行,而是要了解发生了什么,所以我可以在我真正的基准测试中避免它。 解决: Tom Hawtin正确地指出我的“慢”时间实际上是合理的。 根据这一观察,我将调试器附加到Java进程。 在第一个中,内循环看起来像这样: 0xf9037218: cmp %l0, 100 0xf903721c: bge,pn %icc,0xf90371f4 ! 0xf90371f4 0xf9037220: nop 0xf9037224: ld [%l3 + 92], %l2 0xf9037228: ld [%l2 + 8], %l6 0xf903722c: add %l6, 1, %l5 0xf9037230: st %l5, [%l2 […]

为什么lambda IntStream.anyMatch()比天真的实现慢10?

我最近在分析我的代码并发现了一个有趣的瓶颈。 这是基准: @BenchmarkMode(Mode.Throughput) @Fork(1) @State(Scope.Thread) @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) public class Contains { private int[] ar = new int[] {1,2,3,4,5,6,7}; private int val = 5; @Benchmark public boolean naive() { return contains(ar, val); } @Benchmark public boolean lambdaArrayStreamContains() { return Arrays.stream(ar).anyMatch(i […]

奇怪的JIT对循环习语的悲观化

在这里分析最近一个问题的结果时 ,我遇到了一个非常奇怪的现象:显然,HotSpot的JIT优化的额外层实际上减慢了我的机器上的执行速度。 这是我用于测量的代码: @OutputTimeUnit(TimeUnit.NANOSECONDS) @BenchmarkMode(Mode.AverageTime) @OperationsPerInvocation(Measure.ARRAY_SIZE) @Warmup(iterations = 2, time = 1) @Measurement(iterations = 5, time = 1) @State(Scope.Thread) @Threads(1) @Fork(2) public class Measure { public static final int ARRAY_SIZE = 1024; private final int[] array = new int[ARRAY_SIZE]; @Setup public void setup() { final Random random = new Random(); for (int i = 0; […]

为什么边界检查不会被消除?

我写了一个简单的基准测试 ,以便找出当通过按位和数组计算数组时是否可以消除边界检查。 这基本上就是几乎所有哈希表的作用:它们计算 h & (table.length – 1) 作为table的索引,其中h是hashCode或派生值。 结果表明边界检查不会被消除。 我的基准测试的想法很简单:计算两个值i和j ,其中两个值都保证是有效的数组索引。 i是循环计数器。 当它被用作数组索引时,边界检查被消除。 j计算为x & (table.length – 1) ,其中x是每次迭代时改变的某个值。 当它被用作数组索引时,边界检查不会被消除。 相关部分如下: for (int i=0; i<=table.length-1; ++i) { x += result; final int j = x & (table.length-1); result ^= i + table[j]; } 另一个实验使用 result ^= table[i] + j; 代替。 时间的差异可能是15%(在我尝试的不同变体中非常一致)。 我的问题: 除了绑定检查消除之外还有其他可能的原因吗? 是否有一些复杂的原因我无法理解为什么j没有绑定检查消除? […]