Java 多次访问自定义对象的原子属性
哪个函数更快(p是MyObject的原子公共int属性):Java 多次访问自定义对象的原子属性,java,optimization,Java,Optimization,哪个函数更快(p是MyObject的原子公共int属性): 公共静态布尔检查(MyObject o1,列表){ int p=o1.p; 对于(int i=0;i
公共静态布尔检查(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的测试结果:
10%的速度ArrayList
700倍,只需100000个元素LinkedList
- 简短回答:视情况而定
回答稍微长一点:这取决于编译器、虚拟机和虚拟机的设置
背景:在服务器模式下使用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