如果与有条件的速度比较

Ada*_*sen 2 java benchmarking if-statement conditional-operator microbenchmark

我有这个想法,我会使用条件运算符将我的一些if块转换为单行.但是,我想知道是否存在速度差异.我运行了以下测试:

static long startTime;
static long elapsedTime;
static String s;

public static void main(String[] args) {
    startTime = System.nanoTime();
    s = "";
    for (int i= 0; i < 1000000000; i++) {
        if (s.equals("")) {
            s = "";
        }
    }

    elapsedTime = System.nanoTime() - startTime;

    System.out.println("Type 1 took this long: " + elapsedTime + " ns");

    startTime = System.nanoTime();
    s = "";
    for (int i= 0; i < 1000000000; i++) {
        s = (s.equals("") ? "" : s);
    }

    elapsedTime = System.nanoTime() - startTime;

    System.out.println("Type 2 took this long: " + elapsedTime + " ns");
}
Run Code Online (Sandbox Code Playgroud)

这是我的结果:

类型1使用了这么长:3293937157 ns

类型2占用了这么长:2856769127 ns

我在这里做错了吗?

假设s.equals("")必然如此,这是一种使代码更快的可行方法吗?

Rod*_*uin 6

, is this a viable way to make your code faster?
Run Code Online (Sandbox Code Playgroud)

如果您String s;是非静态字段,甚至可以加快速度.当你是referencing十亿次时,静态场比非静态场要慢

public static void main(String[] args) {

    startTime = System.nanoTime();
    String s = "";
    .
    .
}
Run Code Online (Sandbox Code Playgroud)

编辑:

为什么它更快?

这是由于字符串引用到静态字段.

你可以在它的字节码中看到它

    0: ldc           #23                 // String
       2: putstatic     #25                 // Field s:Ljava/lang/String;
       5: iconst_0
       6: istore_1
       7: goto          22
      10: getstatic     #25                 // Field s:Ljava/lang/String;
      13: ldc           #23                 // String
      15: invokevirtual #27                 // Method java/lang/String.equals:(L
java/lang/Object;)Z
      18: pop
      19: iinc          1, 1
      22: iload_1
      23: ldc           #33                 // int 1000000000
      25: if_icmplt     10
      28: return
Run Code Online (Sandbox Code Playgroud)

如你所见getStatic,putStatic将被称为十亿次,它的作用是它将调用静态字段的引用并使用putStatic放置字符串的引用

getStatic - 获取类的静态字段值,其中字段由常量池索引中的字段引用标识(index1 << 8 + index2)

putStatic - 将静态字段设置为类中的值,其中字段由常量池中的字段引用索引标识(indexbyte1 << 8 + indexbyte2)

看看那些导致程序运行缓慢的位移

此外,如果你使用global/member field它将创建相同的字节码,但它将使用 getfield,putfield它与静态getStaticputStatic

现在让我们看看non static field字节码

      0: ldc           #21                 // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: goto          23
       8: aload_1
       9: ldc           #21                 // String
      11: invokevirtual #23                 // Method java/lang/String.equals:(L
java/lang/Object;)Z
      14: ifeq          20
      17: ldc           #21                 // String
      19: astore_1
      20: iinc          2, 1
      23: iload_2
      24: ldc           #29                 // int 1000000000
      26: if_icmplt     8
      29: return
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它只使用astore_1aload_1保存并加载非静态字段的引用而无需额外的操作.

  • 您能否通过提供参考/链接来支持您声称"静态字段比非静态字段慢"? (5认同)

h.j*_*.k. 5

这听起来像是对我的过早优化.如果您仍打算以这种方式对这两种实现isEmpty()进行微基准测试,我建议使用,因为与之相比,底层代码更直接equals().通过这种方式,我的意思是编译器/ JVM将为您做的任何优化都不太可能由正在发生的事情触发equals(),并且更能反映一个实现相对于另一个实现的任何微小优势,假设真的很重要.

可读性应该是您决定是否要使用if-else或更好的规则? :.