首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最小化Java函数调用开销

最小化Java函数调用开销
EN

Stack Overflow用户
提问于 2014-07-21 19:21:00
回答 1查看 1.5K关注 0票数 3

在我运行的每一个测试中,函数调用都有大量的开销。代码是一个紧密的循环,对数组的每个元素(包含4-8百万ints)执行一个非常简单的函数。

运行代码,主要由以下内容组成:

代码语言:javascript
复制
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);
    }
}

执行类似于

代码语言:javascript
复制
(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;
};

在各种机器上(我的工作笔记本电脑、带有W530 3840 VM的i7、具有XeonE5-1620内核的服务器VM和具有一个未知CPU核心的数字海洋节点),在调用方法和内联时,我反复得到了显著的性能影响。所有测试都是在Java 1.8.0_11 ( HotSpot(TM) 64位服务器VM)上进行的.

工作机器:

代码语言:javascript
复制
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

专用服务器,VM:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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倍的性能提升,这可能是值得的,但维护将是一场噩梦。

我不确定是否有一种合理的方法来批量处理一组重复;大多数操作都需要多个输入(调用者不知道)并产生一个输出。

我还有什么其他的选择来最小化开销和晚上的性能呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-21 21:40:43

方法调用不是问题,因为热门方法通常是内联的。虚拟调用是一个问题。

在您的代码中,类型分析器被初始化方法Image.random所愚弄。当Image.process第一次被JIT编译时,它被优化为调用random.nextInt()。因此,下一次对Image.process的调用将导致内联缓存丢失,然后是对Shader.apply的非优化虚拟调用。

  1. 从初始化方法中删除Image.process调用,然后JIT将内联对Shader.apply的有用调用。
  2. BlurShader.apply内联之后,您可以通过替换 最后整数p=s*y+ x; 使用 最后整数p=y*s+ x; 在Image.process中也会遇到后一个表达式,因此JIT不会计算相同的表达式两次。

在应用这两项更改之后,我达到了理想的基准得分:

代码语言:javascript
复制
Benchmark                           Mode   Samples         Mean   Mean error    Units
s.ShaderBench.testProcessInline    thrpt         5       36,483        1,255    ops/s
s.ShaderBench.testProcessLambda    thrpt         5       36,323        0,936    ops/s
s.ShaderBench.testProcessProc      thrpt         5       36,163        1,421    ops/s
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24873010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档