- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
Java 5 为我们提供了 for-each 循环,应尽可能使用它。
但是如果你需要在 block 中使用数组的索引,最有效的习惯用法是什么?
// Option (1)
for (int i = array.length - 1; i >= 0; i--) {
// Code.
}
// Option (2)
for (int i = 0; i < array.length; i++) {
// Code.
}
// Option (3)
for (int i = 0, n = array.length; i < n; i++) {
// Code.
}
(显然,这在大多数程序中不会产生很大的性能差异,但请原谅我。):-)
向后循环并且很丑陋。甚至缓存不友好?还是现代处理器可以检测内存中的后退?
更短,我可以看到 JIT 编译器如何确定 array
永远不会改变,因此 length
是常量,所以它基本上可以用 ( 3).但它这样做了吗? (假设 JVM 是 Oracle 的 Hotspot/Java 7。)
由 Joshua Bloch 在 Effective Java 的第 45 项中建议作为最快的选择,如果它是一些 Collection.size()
这是上限。但它也适用于数组吗?从字节码(见下文)我可以看到每个周期(预优化)保存一条 arraylength
指令。
This question关于 Dalvik 虚拟机中的 for 循环,将 (1)-(3) 列为最快到最慢。然而,这些信息是 2008 年的,今天的 Dalvik 已经成熟得多,所以我不认为情况仍然如此。
看上面例子生成的字节码,有明显的区别:
Compiled from "ForLoops.java"
public class ForLoops extends java.lang.Object{
static int[] array;
public ForLoops();
Code:
0: aload_0
1: invokespecial #10; //Method java/lang/Object."<init>":()V
4: return
public static void forLoop1();
Code:
0: getstatic #17; //Field array:[I
3: arraylength
4: iconst_1
5: isub
6: istore_0
7: goto 13
10: iinc 0, -1
13: iload_0
14: ifge 10
17: return
public static void forLoop2();
Code:
0: iconst_0
1: istore_0
2: goto 8
5: iinc 0, 1
8: iload_0
9: getstatic #17; //Field array:[I
12: arraylength
13: if_icmplt 5
16: return
public static void forLoop3();
Code:
0: iconst_0
1: istore_0
2: getstatic #17; //Field array:[I
5: arraylength
6: istore_1
7: goto 13
10: iinc 0, 1
13: iload_0
14: iload_1
15: if_icmplt 10
18: return
}
最佳答案
您可以轻松地自己测试一下;如果你这样做,你应该看看 these tips about performance testing来自 HotSpot 创作者自己。 This answer也可能有用。如果您决定测试这些实现,请告诉我们您的发现!
不过,总的来说,你不应该太担心这些事情。相反,专注于编写可读代码并完成任务。大多数时候,您会发现您的代码运行速度足够快,无需任何“技巧”。现代硬件非常快,而且 JIT 也非常好。
如果您确实发现您的代码运行速度太慢,请先分析,然后再优化。其他任何事情都为时过早。请记住,来自一个比我们任何人都聪明的人:
"Premature optimization is the root of all evil." -- Donald Knuth
编辑:从“我应该如何编写代码?”的角度来看,您似乎对此不太感兴趣。更就思想实验而言,我期望所有这些选项以或多或少相同的速度运行。
这些循环中没有一个可能会调整分支预测器(无论如何对于合理大小的数组)。我期望底层 JIT 将任何重复出现的数组长度引用从 (2) 样式转换为 (3) 样式。在所有条件相同的情况下,(1) 的缓存性能并不比 (2) 或 (3) 差,仅仅是因为它向后运行;对于给定的数组,相同的缓存行将被加载和命中(或未命中)的频率相同。
当然,我的期望是无关紧要的。唯一知道的方法就是测试!但是,在测试时,请记住 writing good microbenchmarks is hard .
关于java - 哪个迭代数组的习惯用法最有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17515720/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我有实体: @Entity @Table(name = "CARDS") public class Card { @ManyToOne @JoinColumn(name = "PERSON_I
我正在尝试计算二维多边形的表面法线。我正在使用 OpenGL wiki 中的 Newell 方法来计算表面法线。 https://www.opengl.org/wiki/Calculating_a_S
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我这里有以下 XML: Visa, Mastercard, , , , 0, Discover, American Express siteonly, Buyer Pay
即将发生的 Google 政策变更迫使我们实现一个对话框,以通知欧盟用户有关 Cookie/设备标识符用于广告和分析的情况。我只想向欧盟用户显示此对话框。我不想使用额外的权限(例如 android.p
本文分享自华为云社区《华为大咖说 | 企业应用AI大模型的“道、法、术” ——道:认知篇》,作者:华为云PaaS服务小智。 本期核心观点 上车:AGI是未来5~10年内,每个人都无法回避的技
我有一个与酒精相关的网站,需要先验证年龄,然后才能让他们进入该网站。我使用 HttpModule 来执行此操作,该模块检查 cookie,如果未设置,我会将它们重定向到验证页面。我验证他们的年龄并存储
在欧盟,我们有一项法律,要求网页请求存储 cookie 的许可。我们大多数人都了解 cookie 并同意它们,但仍然被迫在任何地方明确接受它们。所以我计划编写这个附加组件(ff & chrome),它
以下在 C 和/或 C++ 中是否合法? void fn(); inline void fn() { /*Do something here*/ } 让我担心的是,第一个声明看起来暗示函数将被定义
我是一名优秀的程序员,十分优秀!