Java for loop performance question

前端 未结 13 1198
长发绾君心
长发绾君心 2020-12-15 05:17

considering this example:

public static void main(final String[] args) {
    final List myList = Arrays.asList(\"A\", \"B\", \"C\", \"D\");
            


        
13条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-15 05:46

    Personally, I don't think you can draw any meaningful conclusions from a contrived example like this.

    But if you really want to know, why not use javap to decompile the code and see what's different? Why guess about what the compiler's doing when you can see for yourself without asking here?

    Byte code for the first case:

    public class Stackoverflow extends java.lang.Object{
    public Stackoverflow();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."":()V
       4:   return
    
    public static void main(java.lang.String[]);
      Code:
       0:   iconst_4
       1:   anewarray       #2; //class java/lang/String
       4:   dup
       5:   iconst_0
       6:   ldc     #3; //String A
       8:   aastore
       9:   dup
       10:  iconst_1
       11:  ldc     #4; //String B
       13:  aastore
       14:  dup
       15:  iconst_2
       16:  ldc     #5; //String C
       18:  aastore
       19:  dup
       20:  iconst_3
       21:  ldc     #6; //String D
       23:  aastore
       24:  invokestatic    #7; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List
       27:  astore_1
       28:  invokestatic    #8; //Method java/lang/System.currentTimeMillis:()J
       31:  lstore_2
       32:  ldc     #9; //int 1000000
       34:  istore  4
       36:  iload   4
       38:  aload_1
       39:  invokeinterface #10,  1; //InterfaceMethod java/util/List.size:()I
       44:  if_icmple       61
       47:  getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
       50:  ldc     #12; //String Hello
       52:  invokevirtual   #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       55:  iinc    4, -1
       58:  goto    36
       61:  invokestatic    #8; //Method java/lang/System.currentTimeMillis:()J
       64:  lstore  4
       66:  getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
       69:  new     #14; //class java/lang/StringBuilder
       72:  dup
       73:  invokespecial   #15; //Method java/lang/StringBuilder."":()V
       76:  ldc     #16; //String Finish:
       78:  invokevirtual   #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/la
       81:  lload   4
       83:  lload_2
       84:  lsub
       85:  invokevirtual   #18; //Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
       88:  invokevirtual   #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       91:  invokevirtual   #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       94:  return
    }
    

    Byte code for the second case:

    public class Stackoverflow extends java.lang.Object{
    public Stackoverflow();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."":()V
       4:   return
    
    public static void main(java.lang.String[]);
      Code:
       0:   iconst_4
       1:   anewarray       #2; //class java/lang/String
       4:   dup
       5:   iconst_0
       6:   ldc     #3; //String A
       8:   aastore
       9:   dup
       10:  iconst_1
       11:  ldc     #4; //String B
       13:  aastore
       14:  dup
       15:  iconst_2
       16:  ldc     #5; //String C
       18:  aastore
       19:  dup
       20:  iconst_3
       21:  ldc     #6; //String D
       23:  aastore
       24:  invokestatic    #7; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
       27:  astore_1
       28:  invokestatic    #8; //Method java/lang/System.currentTimeMillis:()J
       31:  lstore_2
       32:  aload_1
       33:  invokeinterface #9,  1; //InterfaceMethod java/util/List.size:()I
       38:  istore  4
       40:  ldc     #10; //int 1000000
       42:  istore  5
       44:  iload   5
       46:  iload   4
       48:  if_icmple       65
       51:  getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
       54:  ldc     #12; //String Hello
       56:  invokevirtual   #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       59:  iinc    5, -1
       62:  goto    44
       65:  invokestatic    #8; //Method java/lang/System.currentTimeMillis:()J
       68:  lstore  5
       70:  getstatic       #11; //Field java/lang/System.out:Ljava/io/PrintStream;
       73:  new     #14; //class java/lang/StringBuilder
       76:  dup
       77:  invokespecial   #15; //Method java/lang/StringBuilder."":()V
       80:  ldc     #16; //String Finish:
       82:  invokevirtual   #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       85:  lload   5
       87:  lload_2
       88:  lsub
       89:  invokevirtual   #18; //Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
       92:  invokevirtual   #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       95:  invokevirtual   #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       98:  return
    }
    

    There are differences, but I'm not sure I can make a definitive statement about their effect on performance.

    I'd code the second one, because it would mean (on the face of it) one method call as opposed to one per loop iteration. I don't know if the compiler can optimize it away, but I'm certain that I can do it pretty easily. So I do, regardless of its effect on wall time.

提交回复
热议问题