Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

It seems common practice to extract a constant empty array return value into a static constant. Like here:

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

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

    // ...
}

Presumably this is done for performance reasons, since returning new String[0] directly would create a new array object every time the method is called – but would it really?

I've been wondering if there really is a measurable performance benefit in doing this or if it's just outdated folk wisdom. An empty array is immutable. Is the VM not able to roll all empty String arrays into one? Can the VM not make new String[0] basically free of cost?

Contrast this practice with returning an empty String: we're usually perfectly happy to write return "";, not return EMPTY_STRING;.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
178 views
Welcome To Ask or Share your Answers For Others

1 Answer

I benchmarked it using 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) {
}

Full source code.

Environment (seen after 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: <none>
# 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 was on by default (seen after java -XX:+PrintFlagsFinal -version | grep EliminateAllocations).

Results:

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

Using a constant was almost two times faster.

Turning off EliminateAllocations slowed things down a tiny bit.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...