rod*_*ded 17 java performance java-7
我正在将Spring 3.1.2批处理应用程序迁移jdk1.7.0_25到jdk1.7.0_40x64和Oracle.
使用Sun OperatingSystemMXBean.getProcessCpuTime()作为性能指标,结果显示性能下降2.5倍(即,我在u25上运行的应用程序要快得多).
java.util.HashMap和java.util.ArrayList 更改,因为当使用u25的HashMap和ArrayList类引导u40时结果是相同的,并且这些更改对于这种差异来说太小了.-Xbatch并-Xcomp产生相同的结果(假设这些JDK之间的服务器编译是相同的).java.lang.invoke.MethodHandles但似乎无关.除非Spring 3.1.2使用它们 - 我找不到它的证据.javac 编译似乎也没有改变.一些一般性说明:
jdk1.8.0)都会出现此问题,而版本<u40似乎很好(包括各种版本的JDK 6).+UseSerialGC用于测试).jdk1.7.0_40.任何提示或想法?
编辑添加:应用程序的结构是一个外部循环,运行金融蒙特卡罗模拟:即大量的日期,计算等.因此,它目前有点复杂,我同意,不适合找到问题.我将不得不尝试将其缩小.
看起来这个问题是由于在JDK-7133857中完成的工作,其中java.lang.Math.pow()并java.lang.Math.exp()使用x87进行了内部化和计算.
这些方法在分析的应用程序中被广泛使用(!),因此它们具有相当大的效果.
JDK-8029302描述并修复了2个输入功率的问题; 并且对应用程序的测试jdk1.8.0_25(其中问题已得到修复)显示出改进的性能,尽管没有回到jdk1.7.0_25内在化之前的更高级别.
以下是我的JMH基准测试及其Math.pow()在三个相关JDK版本上的结果:
package org.sample;
import org.openjdk.jmh.annotations.*;
import java.lang.*;
public class MyBenchmark {
@State(Scope.Benchmark)
public static class ThreadState {
volatile double x = 0;
volatile double y = 0;
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public double powx(ThreadState state) {
state.x++;
state.y += 0.5;
return Math.pow(state.x, state.y);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public double pow3(ThreadState state) {
state.x++;
return Math.pow(state.x, 3);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public double pow2(ThreadState state) {
state.x++;
return Math.pow(state.x, 2);
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
Intel(R)Core(TM)i5-2520M CPU @ 2.50GHz
# VM invoker: x:\@sdks\jdks\jdk1.7.0_25\jre\bin\java.exe
...
Result: 4877658.355 (99.9%) 330460.323 ops/s [Average]
Statistics: (min, avg, max) = (1216417.493, 4877658.355, 6421780.276), stdev = 1399189.700
Confidence interval (99.9%): [4547198.032, 5208118.678]
# Run complete. Total time: 00:24:48
Benchmark Mode Samples Score Score error Units
o.s.MyBenchmark.pow2 thrpt 200 40160618.138 1561135.596 ops/s
o.s.MyBenchmark.pow3 thrpt 200 3678800.153 88678.269 ops/s
o.s.MyBenchmark.powx thrpt 200 4877658.355 330460.323 ops/s
Run Code Online (Sandbox Code Playgroud)
# VM invoker: x:\@sdks\jdks\jdk1.7.0_40\jre\bin\java.exe
...
Result: 1860849.245 (99.9%) 94303.387 ops/s [Average]
Statistics: (min, avg, max) = (418909.582, 1860849.245, 2379936.035), stdev = 399286.444
Confidence interval (99.9%): [1766545.859, 1955152.632]
# Run complete. Total time: 00:24:48
Benchmark Mode Samples Score Score error Units
o.s.MyBenchmark.pow2 thrpt 200 9619333.987 230749.333 ops/s
o.s.MyBenchmark.pow3 thrpt 200 9240043.369 238456.949 ops/s
o.s.MyBenchmark.powx thrpt 200 1860849.245 94303.387 ops/s
Run Code Online (Sandbox Code Playgroud)
# VM invoker: x:\@sdks\jdks\jdk1.8.0_25\jre\bin\java.exe
...
Result: 1898015.057 (99.9%) 92555.236 ops/s [Average]
Statistics: (min, avg, max) = (649562.297, 1898015.057, 2359474.902), stdev = 391884.665
Confidence interval (99.9%): [1805459.821, 1990570.293]
# Run complete. Total time: 00:24:37
Benchmark Mode Samples Score Score error Units
o.s.MyBenchmark.pow2 thrpt 200 81840274.815 1979190.065 ops/s
o.s.MyBenchmark.pow3 thrpt 200 9441518.686 206612.404 ops/s
o.s.MyBenchmark.powx thrpt 200 1898015.057 92555.236 ops/s
Run Code Online (Sandbox Code Playgroud)
如果我正确读到这一点,那么2问题的力量肯定在JDK-8029302中得到了解决,并且功率> 2 ints(我刚刚测试过Math.pow(x, 3))的性能得到了提升jdk1.7.0_40.至于怪异的非INT Math.pow()s如上面的做powx()标杆,似乎有移动时仍然是一个相当大的性能回归(> 3倍)jdk1.7.0_25至jdk1.7.0_40.
更换Math.pow()并Math.exp()使用各自的方法可以org.apache.commons.math3.util.FastMath完全解决问题并提高性能 - 就我而言,这是正确的解决方案.
注意:如果有一种简单的方法(即不需要构建JDK)来设置-XX:-InlineIntrinsics标志,这将会更简单一些.
| 归档时间: |
|
| 查看次数: |
441 次 |
| 最近记录: |