Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多次访问自定义对象的原子属性_Java_Optimization - Fatal编程技术网

Java 多次访问自定义对象的原子属性

Java 多次访问自定义对象的原子属性,java,optimization,Java,Optimization,哪个函数更快(p是MyObject的原子公共int属性): 公共静态布尔检查(MyObject o1,列表){ int p=o1.p; 对于(int i=0;i

哪个函数更快(p是MyObject的原子公共int属性):

公共静态布尔检查(MyObject o1,列表){
int p=o1.p;
对于(int i=0;i<1000000;i++){
MyObject o=list.get(i);
如果(o.p

公共静态布尔检查(MyObject o1,列表){
对于(int i=0;i<1000000;i++){
MyObject o=list.get(i);
如果(o.p

因此,通过使用局部变量p,我们可以缓存对象属性调用,或者由编译器优化内联完成。

javac
编译器几乎不进行优化


然而,JIT可以显著优化代码,包括在寄存器中存储字段。

虽然不是直接在主题上,但您可以通过使用“foreach”循环改进样式并实现更高的恒定速度:

for(MyObject o:list){
如果(o.p
切换到foreach的测试结果:

  • ArrayList
    10%的速度
  • LinkedList
    700倍,只需100000个元素

    • 简短回答:视情况而定

      回答稍微长一点:这取决于编译器、虚拟机和虚拟机的设置

      背景:在服务器模式下使用HotSpot VM(最常见的风格)将使这两种变体相等,因为VM在服务器模式下不循环。在客户机模式下,如果虚拟机认为值得优化,则可以完成,也可以不完成,甚至可以在以后完成

      是一种循环优化,在大多数现代编译器(或Java、VM)中实现。至于javac生成的代码:没有VM的进一步优化,您的第一个代码片段将运行得更快

      public static boolean check(Test$MyObject, java.util.List);
        Code:
         0:   aload_0
         1:   getfield        #7; //Field Test$MyObject.p:I
         4:   istore_2
         5:   iconst_0
         6:   istore_3
         7:   iload_3
         8:   ldc     #4; //int 1000000
         10:  if_icmpge       42
         13:  aload_1
         14:  iload_3
         15:  invokeinterface #11,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
         20:  checkcast       #5; //class Test$MyObject
         23:  astore  4
         25:  aload   4
         27:  getfield        #7; //Field Test$MyObject.p:I
         30:  iload_2
         31:  if_icmpge       36
         34:  iconst_0
         35:  ireturn
         36:  iinc    3, 1
         39:  goto    7
         42:  iconst_1
         43:  ireturn
      
      --


      如您所见,第二个示例中第20行的getfield操作位于第一个示例中的第1行,并且在循环之外(变体1中的第7行到39行,变体2中的第2行到35行),因此只执行了一次而不是1000000次。

      我不知道Java中有一个
      原子的
      关键字,我在谷歌上找不到任何参考资料也许她是说她用的是原子整数?显然,第二种选择不可能比第二种快。因此,问题只是“这至少和以前一样快吗?”答案是“可能”。Eclipse的编译器(来自IBM)生成的代码几乎与Oracle HotSpot的编译器相同。对于每个循环来说,都是有史以来最慢的循环:)这是关于IMHO的主题。如果调用方传递一个LinkedList,它将使执行时间加快大约200000倍(foreach循环使用迭代器,其中获取下一个元素是O(1)。get(i)将遍历读取的每个元素的列表。我刚刚在
      ArrayList
      上做了一个简单的测试,你说得对!但它只慢了大约10%。它看起来确实更好:),但并非所有
      列表的原始形式都会更快。至少可以保证您的性能相当稳定
      
      public static boolean check(MyObject o1, List<MyObject> list) {
      
          for (int i = 0; i < 1000000; i++) {
              MyObject o = list.get(i);
              if (o.p < o1.p) return false;
          }
      
          return true;
      }
      
      for (MyObject o : list) {
          if (o.p < o1.p) return false;
      }
      
      public static boolean check(Test$MyObject, java.util.List);
        Code:
         0:   aload_0
         1:   getfield        #7; //Field Test$MyObject.p:I
         4:   istore_2
         5:   iconst_0
         6:   istore_3
         7:   iload_3
         8:   ldc     #4; //int 1000000
         10:  if_icmpge       42
         13:  aload_1
         14:  iload_3
         15:  invokeinterface #11,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
         20:  checkcast       #5; //class Test$MyObject
         23:  astore  4
         25:  aload   4
         27:  getfield        #7; //Field Test$MyObject.p:I
         30:  iload_2
         31:  if_icmpge       36
         34:  iconst_0
         35:  ireturn
         36:  iinc    3, 1
         39:  goto    7
         42:  iconst_1
         43:  ireturn
      
      public static boolean check(Test$MyObject, java.util.List);
        Code:
         0:   iconst_0
         1:   istore_2
         2:   iload_2
         3:   ldc     #4; //int 1000000
         5:   if_icmpge       38
         8:   aload_1
         9:   iload_2
         10:  invokeinterface #11,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
         15:  checkcast       #5; //class Test$MyObject
         18:  astore_3
         19:  aload_3
         20:  getfield        #7; //Field Test$MyObject.p:I
         23:  aload_0
         24:  getfield        #7; //Field Test$MyObject.p:I
         27:  if_icmpge       32
         30:  iconst_0
         31:  ireturn
         32:  iinc    2, 1
         35:  goto    2
         38:  iconst_1
         39:  ireturn