【发布时间】:2014-09-12 10:12:39
【问题描述】:
我有a piece of code,在我运行的每个测试中,函数调用都会产生大量开销。代码是一个紧密的循环,对数组的每个元素执行一个非常简单的函数(包含 4-8 百万ints)。
运行代码,主要包括
for (int y = 1; y < h; ++y) {
for (int x = 1; x < w; ++x) {
final int p = y * s + x;
n[p] = f.apply(d, s, x, y);
}
}
执行类似的操作
(final int[] d, final int s, final int x, final int y) -> {
final int p = s * y + x;
final int a = d[p] * 2
+ d[p - 1]
+ d[p + 1]
+ d[p - s]
+ d[p + s];
return (1000 * (a + 500)) / 6000;
};
在各种机器上(我的工作笔记本电脑、带有 i7 3840QM 的 W530、带有 Xeon E5-1620 一个核心的服务器 VM,以及一个带有一个未知 CPU 核心的 Digital Ocean 节点),我反复得到统计显着性调用方法与内联时性能受到影响。所有测试均在 Java 1.8.0_11(Java HotSpot(TM) 64 位服务器虚拟机)上执行。
工作机器:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 40.860 0.184 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 22.603 0.159 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 22.792 0.117 ops/s
专用服务器,虚拟机:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 40.685 0.224 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 16.077 0.113 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 23.827 0.088 ops/s
做 VPS:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 24.425 0.506 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 9.643 0.140 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 13.733 0.134 ops/s
所有可接受的性能,但我有兴趣弄清楚为什么调用会有如此大的开销以及可以做些什么来优化它。目前正在试验不同的参数集。
内联所有潜在的操作会很困难,但理论上是可行的。将性能提高近 2 倍,这可能是值得的,但维护将是一场噩梦。
我不确定是否有合理的方法来批量处理一组重复;大多数操作需要多个输入(调用者不知道)并产生一个输出。
我还有哪些其他选项可以最大程度地减少开销和夜间性能?
【问题讨论】:
-
仅供想回答的人参考,
f函数实际上是一个普通的接口方法,而不是@functionalInterface -
@dkatzel 这是我的一个错误(这是一个使用 Java 8 的项目的一部分),尽管如果它以某种方式有帮助,可以保留一个。
f可以由类或 lambda 填充,这一点相当重要。
标签: java performance optimization java-8 jmh