为什么流利的执行速度比不流利的执行速度慢?

Boh*_*ian 2 java performance fluent-interface

我写了一些测试代码,它将使用8次append()方法 的速度StringBuilder作为一个流畅的接口进行比较,而不是分别在8行中调用它.

流利:

StringBuilder s = new StringBuilder();
s.append(x)
.append(y)
.append(z); //etc
Run Code Online (Sandbox Code Playgroud)

由于不流利:

StringBuilder s = new StringBuilder();
s.append(x)
s.append(y)
s.append(z); //etc
Run Code Online (Sandbox Code Playgroud)

每种方法都被调用了1000万次.在每个块之间调用GC.执行版本的顺序颠倒了相同的结果.

我的测试显示,代码的流畅版本慢了大约10%(fyi,测试代码是公平的,匹配但不可预测的附加,我给了时间JVM热身等).

这是一个惊喜,因为流畅的代码是一行.

为什么不流畅的代码会更快?

Pet*_*rey 6

我怀疑它是某些Java版本的一个特性.

如果我运行以下

public class Main {

    public static final int RUNS = 100000000;

    static final ThreadLocal<StringBuilder> STRING_BUILDER_THREAD_LOCAL = new ThreadLocal<StringBuilder>() {
        @Override
        protected StringBuilder initialValue() {
            return new StringBuilder();
        }
    };

    public static final StringBuilder myStringBuilder() {
        StringBuilder sb = STRING_BUILDER_THREAD_LOCAL.get();
        sb.setLength(0);
        return sb;
    }

    public static long testSeparate(String x, String y, String z) {
        long start = System.nanoTime();
        for (int i = 0; i < RUNS; i++) {
            StringBuilder s = myStringBuilder();
            s.append(x)
                    .append(y)
                    .append(z);
            dontOptimiseAway = s.toString();
        }
        long time = System.nanoTime() - start;
        return time;
    }

    public static long testChained(String x, String y, String z) {
        long start = System.nanoTime();
        for (int i = 0; i < RUNS; i++) {
            StringBuilder s = myStringBuilder();
            s.append(x);
            s.append(y);
            s.append(z);
            dontOptimiseAway = s.toString();
        }
        long time = System.nanoTime() - start;
        return time;
    }

    static String dontOptimiseAway = null;

    public static void main(String... args) {
        for (int i = 0; i < 10; i++) {
            long time1 = testSeparate("x", "y", "z");
            long time2 = testChained("x", "y", "z");
            System.out.printf("Average time separate %.1f ns, chained %.1f ns%n",
                    (double) time1 / RUNS, (double) time2 / RUNS);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用Java 7更新4

Average time separate 49.8 ns, chained 49.0 ns
Average time separate 50.7 ns, chained 49.3 ns
Average time separate 46.9 ns, chained 46.5 ns
Average time separate 46.6 ns, chained 46.4 ns
Average time separate 46.6 ns, chained 46.6 ns
Average time separate 47.6 ns, chained 47.3 ns
Average time separate 46.7 ns, chained 47.2 ns
Average time separate 46.7 ns, chained 47.0 ns
Average time separate 46.0 ns, chained 46.6 ns
Average time separate 46.7 ns, chained 46.3 ns
Run Code Online (Sandbox Code Playgroud)

使用Java 7更新10

Average time separate 50.4 ns, chained 50.0 ns
Average time separate 50.1 ns, chained 50.1 ns
Average time separate 45.9 ns, chained 46.5 ns
Average time separate 46.6 ns, chained 46.7 ns
Average time separate 46.3 ns, chained 46.4 ns
Average time separate 46.7 ns, chained 46.5 ns
Average time separate 46.2 ns, chained 46.4 ns
Average time separate 46.6 ns, chained 46.0 ns
Average time separate 46.4 ns, chained 46.2 ns
Average time separate 45.9 ns, chained 46.2 ns
Run Code Online (Sandbox Code Playgroud)

最初可能看起来略有偏差,但如果您的运行更新10,则随着时间的推移没有明显的偏差.