Speed of if compared to conditional

孤街浪徒 提交于 2019-12-07 19:18:44

问题


I had the idea I would turn some of my if blocks into single lines, using the conditional operator. However, I was wondering if there would be a speed discrepancy. I ran the following test:

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");
}

This is my result:

Type 1 took this long: 3293937157 ns

Type 2 took this long: 2856769127 ns

Am I doing something wrong here?

Assuming s.equals("") necessarily is true, is this a viable way to make your code faster?


回答1:


The other answers have useful information that is relevant but none of them addresses the real question if the first form is more efficient than the second form.

This benchmarking does not provide reliable results since it's not done properly: one important "rule of thumb" in benchmarking Java code is to provide a warm-up. In this case, the first loop provides a warm-up to the second loop.

This answer provides additional instructions for micro-benchmarking as well as some useful links.




回答2:


, is this a viable way to make your code faster?

You can even make it faster if your String s; is a non static field. Static-field is slower than non-static field when you are referencing it a billion times

public static void main(String[] args) {

    startTime = System.nanoTime();
    String s = "";
    .
    .
}

EDIT:

Why is it faster??

It is due to the referencing of string to the static field.

You can see it in the byte code of it

    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

As you can see getStatic and putStatic will be called a billion times, what it does is that it will call the reference of the static field and put the reference of the string using putStatic

getStatic - get a static field value of a class, where the field is identified by field reference in the constant pool index (index1 << 8 + index2)

putStatic - set static field to value in a class, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 + indexbyte2)

See those bit shifting that is the cause of the slowness of the program

Also if you are using a global/member field it will create the same bytecode but instead it will use getfield and putfield which is the same as static's getStatic and putStatic

Now let see the non static field bytecode

      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

As you can see it only uses astore_1 and aload_1 to save and load the reference of the non static field without extra operation.




回答3:


This does smell like premature optimization to me. If you still intend to microbenchmark both implementations this way, I suggest using isEmpty() instead since the underlying code for that is more straightforward compared to equals(). By that, I mean any optimization that the compiler/JVM will do for you will be less likely triggered by what's happening in equals(), and more reflective of any minute benefits that one implementation has over the other, assuming that really matters.

Readability should be the better rule for you to decide whether you want to use if-else or ? :.



来源:https://stackoverflow.com/questions/25029785/speed-of-if-compared-to-conditional

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!