当前位置:  开发笔记 > 编程语言 > 正文

静态空数组实例的性能优势

如何解决《静态空数组实例的性能优势》经验,为你挑选了1个好方法。

通常的做法是将常量空数组返回值提取为静态常量.像这儿:

public class NoopParser implements Parser {
    private static final String[] EMPTY_ARRAY = new String[0];

    @Override public String[] supportedSchemas() {
        return EMPTY_ARRAY;
    }

    // ...
}

可能这是出于性能原因而完成的,因为new String[0]每次调用该方法时直接返回会创建一个新的数组对象 - 但它真的会吗?

我一直想知道这样做是否真的有可衡量的性能优势,或者它是否只是过时的民间智慧.空数组是不可变的.VM是否无法将所有空String数组卷成一个?VM new String[0]基本上没有成本吗?

将这种做法与返回一个空字符串进行对比:我们通常很乐意写return "";,而不是return EMPTY_STRING;.



1> Adam Stelmas..:

我使用JMH对它进行了基准测试:

private static final String[] EMPTY_STRING_ARRAY = new String[0];

@Benchmark
public void testStatic(Blackhole blackhole) {
    blackhole.consume(EMPTY_STRING_ARRAY);
}

@Benchmark
@Fork(jvmArgs = "-XX:-EliminateAllocations")
public void testStaticEliminate(Blackhole blackhole) {
    blackhole.consume(EMPTY_STRING_ARRAY);
}

@Benchmark
public void testNew(Blackhole blackhole) {
    blackhole.consume(new String[0]);
}

@Benchmark
@Fork(jvmArgs = "-XX:-EliminateAllocations")
public void testNewEliminate(Blackhole blackhole) {
    blackhole.consume(new String[0]);
}

@Benchmark
public void noop(Blackhole blackhole) {
}

完整的源代码。

环境(见后java -jar target/benchmarks.jar -f 1):

# JMH 1.11.2 (released 51 days ago)
# VM version: JDK 1.7.0_75, VM 24.75-b04
# VM invoker: /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
# VM options: 
# Warmup: 20 iterations, 1 s each
# Measurement: 20 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time

EliminateAllocations默认情况下处于开启状态(在之后可见java -XX:+PrintFlagsFinal -version | grep EliminateAllocations)。

结果:

Benchmark                         Mode  Cnt           Score         Error  Units
MyBenchmark.testNewEliminate     thrpt   20    95912464.879 ± 3260948.335  ops/s
MyBenchmark.testNew              thrpt   20   103980230.952 ± 3772243.160  ops/s
MyBenchmark.testStaticEliminate  thrpt   20   206849985.523 ± 4920788.341  ops/s
MyBenchmark.testStatic           thrpt   20   219735906.550 ± 6162025.973  ops/s
MyBenchmark.noop                 thrpt   20  1126421653.717 ± 8938999.666  ops/s

使用常数几乎快了两倍。

关闭电源EliminateAllocations会使速度变慢。


即使使用JMH,这也是一个非常不公平的基准。1)手动编写基准循环是一个错误;JMH为您做到。2)黑洞不消耗结果。3)测试无法比较:`testNew`消耗大量内存,因为它将所有中间结果保存在一起;在实际实践中,这不是通常的情况。4)测试的编写方式使JVM无法应用分配消除优化,但是这种优化对于处理从方法返回的短期对象至关重要(请参阅http://stackoverflow.com/questions/33765687/)。
推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有