Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.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_Android_Optimization_Dalvik - Fatal编程技术网

通过Java列表的高效循环

通过Java列表的高效循环,java,android,optimization,dalvik,Java,Android,Optimization,Dalvik,下面的列表来自于2008年的google I/O对话,名为“Dalvik Virtual Machine Internals”,它是一个按从最高效率到最低效率的顺序循环一组对象的方法列表: (1) for (int i = initializer; i >=0; i--) //hard to loop backwards (2) int limit = calculate_limit(); for (int i= 0; i< limit; i++) (3) Type[] array

下面的列表来自于2008年的google I/O对话,名为“Dalvik Virtual Machine Internals”,它是一个按从最高效率到最低效率的顺序循环一组对象的方法列表:

(1) for (int i = initializer; i >=0; i--) //hard to loop backwards
(2) int limit = calculate_limit(); for (int i= 0; i< limit; i++)
(3) Type[] array = get_array(); for (Type obj : array)
(4) for (int i =0; i< array.length; i++) //gets array.length everytime
(5) for (int i=0; i < this.var; i++) //has to calculate what this.var is
(6) for (int i=0; i < obj.size(); i++) //even worse calls function  each time
(7) Iterable list = get_list(); for (Type obj : list) //generic object based iterators slow!
(1)for(int i=initializer;i>=0;i--)//很难向后循环
(2) int limit=计算_limit();对于(int i=0;i
前3个在同一效率范围内,尽可能避免使用7个。这主要是帮助延长电池寿命的建议,但也可能对JavaSE代码有所帮助


我的问题是:为什么(7)慢,为什么(3)好?我想这可能是(3)和(7)的数组和列表之间的区别。此外,正如Dan提到的(7)创建了大量必须GCD的小临时对象,我现在对Java有点生疏,有人能解释为什么吗?它在他的0:41:10出现了一分钟。

我想你必须将对象打包成一个基于“链表”的迭代器,然后支持一个API,而不是一块内存和一个指针(数组)

第三个变体比7快,因为数组是具体化类型,JVM应该只分配一个指针到一个正确的值。但当您在集合上迭代时,编译器会因为擦除而执行额外的强制转换。实际上,编译器会将这种类型转换为泛型代码,以尽快确定一些肮脏的黑客行为,比如使用不推荐的原始类型


p.S.这只是一个猜测。事实上,我认为编译器和JIT编译器可以执行任何优化(即使在运行时也可以执行JIT),并且结果可能取决于特定的细节,如JVM版本和供应商。

我猜编译器优化(3)到这一点(这是我猜测的部分):


我觉得我的第一个答案并不令人满意,也无法解释这个问题;我已经发布了到的链接并详细阐述了一些内容,这些内容涵盖了一些基本的用例,但没有涉及问题的实质。所以,我继续做了一些实际的研究

我运行了两个不同的代码:

    // Code 1
    int i = 0;
    Integer[] array = { 1, 2, 3, 4, 5 };
    for (Integer obj : array) {
        i += obj;
    }
    System.out.println(i);

    // Code 2
    int i = 0;
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    for (Integer obj : list) {
        i += obj;
    }
    System.out.println(i);
//代码1
int i=0;
整数[]数组={1,2,3,4,5};
for(整数对象:数组){
i+=obj;
}
系统输出打印LN(i);
//代码2
int i=0;
列表=新的ArrayList();
增加第(1)款;
增加(2);
增加(3);
增加(4);
增加(5);
对于(整数对象:列表){
i+=obj;
}
系统输出打印LN(i);
当然,两者都打印出
15
,并且都使用
Integer
数组(no
int
s)

接下来,我使用
javap
来分解这些代码并查看字节码。(我忽略了初始化;在
for
循环之前的所有内容都被注释掉了。)由于这些内容相当长,我将它们发布在PasteBin上

现在,虽然代码1的字节码实际上较长,但强度较低。它只使用一次
invokevirtual
(除了
println
),不需要其他调用。在代码1中,它似乎将迭代优化为基本循环;检查数组长度,并加载到变量中,然后添加到
i
。这似乎被优化为与(inti=0;i的行为完全相同

现在,在代码2中,字节码变得更加密集。除了上面需要的每一次调用之外,它还必须进行2次调用(都是对迭代器的调用)。此外,代码2必须调用
checkcast
,因为它是一个通用的
迭代器(正如我前面提到的,它没有经过优化)。现在,尽管对
load
store
操作的调用较少,但上述调用涉及的开销要大得多


正如他在视频中所说,如果你发现自己需要做很多这些事情,你可能会遇到问题。例如,在
活动开始时运行一个
,可能没什么大不了的。只需注意创建其中的许多,尤其是在
onDraw
中进行迭代。

这个列表有点过时,今天应该没有什么用处

几年前,当Android设备运行缓慢且资源非常有限时,这是一个很好的参考。Dalvik VM实现目前也缺乏很多可用的优化

在这样的设备上,一次简单的垃圾收集很容易花费1到2秒(相比之下,现在大多数设备上大约需要20毫秒)。在GC期间,设备冻结,因此开发人员必须非常小心内存消耗

今天您不必太担心这一点,但如果您真的关心性能,以下是一些细节:

(1) for (int i = initializer; i >= 0; i--) //hard to loop backwards
(2) int limit = calculate_limit(); for (int i=0; i < limit; i++)
(3) Type[] array = get_array(); for (Type obj : array)
评论中已经解释了这些问题

(7) Iterable list = get_list(); for (Type obj : list)

Iterables
很慢,因为它们分配内存,执行一些错误处理,在内部调用多个方法。。。所有这些都比(6)慢得多,后者在每次迭代中只执行一个函数调用。

对于Android,这是2015年谷歌开发者发布的视频

是索引还是迭代?(Android性能模式第二季ep6)

他们在DALVIK运行时4.4.4版本上进行了10次测试,得到了平均结果。 结果表明,“为指数”是最好的

int size=list.size();
对于(int index=0;index}
JVM是一个堆栈机器,那么为什么内存分配很昂贵呢?JVM应该只向前移动堆栈指针。JVM也有一个堆。。。您使用的每个
都是在he上创建的
(1) for (int i = initializer; i >= 0; i--) //hard to loop backwards
(2) int limit = calculate_limit(); for (int i=0; i < limit; i++)
(3) Type[] array = get_array(); for (Type obj : array)
(4) for (int i=0; i < array.length; i++) //gets array.length everytime
(5) for (int i=0; i < this.var; i++) //has to calculate what this.var is
(6) for (int i=0; i < obj.size(); i++) //even worse calls function  each time
(7) Iterable list = get_list(); for (Type obj : list)