- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我今天在 Java 教程中阅读了以下代码。
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0, n = elements.length; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
作为新手,我可能会写出如下代码。
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0; i < elements.length; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
或者像下面这样。
int n = elements.length;
for (int i = 0; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
我只想问一下它们有什么区别?有没有其他更优秀的方法来优化 Java 中的 for 循环?
最佳答案
优化的黄金法则是,不要。
第二条黄金法则是,还没有。
第三条黄金法则实际上是一个问题,你测量了吗?
回答您的问题时,请遵循您团队中公认的标准:您的代码不应该有任何不同,除非它做了一些真正不同的事情。也就是说,在一个好的团队中,代码都是相似且乏味的。任何一步都是一个巨大的闪光标志,上面写着:“小心,这是规则的异常(exception)!” - 除非您想确切地说,否则请使用其他人使用的任何东西。
现在,在代码方面,答案在编译器中:
import java.util.logging.*;
public class ForLoop {
private static Logger logger = Logger.getLogger("log");
public static void a(Throwable e) {
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0, n = elements.length; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
public static void b(Throwable e) {
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0; i < elements.length; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
public static void c(Throwable e) {
StackTraceElement elements[] = e.getStackTrace();
int n = elements.length;
for (int i = 0; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
}
编译成
alf-pro:Learning alf$ javap -p -c ForLoop.class
Compiled from "ForLoop.java"
public class ForLoop {
private static java.util.logging.Logger logger;
public ForLoop();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void a(java.lang.Throwable);
Code:
0: aload_0
1: invokevirtual #2 // Method java/lang/Throwable.getStackTrace:()[Ljava/lang/StackTraceElement;
4: astore_1
5: iconst_0
6: istore_2
7: aload_1
8: arraylength
9: istore_3
10: iload_2
11: iload_3
12: if_icmpge 36
15: getstatic #3 // Field logger:Ljava/util/logging/Logger;
18: getstatic #4 // Field java/util/logging/Level.WARNING:Ljava/util/logging/Level;
21: aload_1
22: iload_2
23: aaload
24: invokevirtual #5 // Method java/lang/StackTraceElement.getMethodName:()Ljava/lang/String;
27: invokevirtual #6 // Method java/util/logging/Logger.log:(Ljava/util/logging/Level;Ljava/lang/String;)V
30: iinc 2, 1
33: goto 10
36: return
public static void b(java.lang.Throwable);
Code:
0: aload_0
1: invokevirtual #2 // Method java/lang/Throwable.getStackTrace:()[Ljava/lang/StackTraceElement;
4: astore_1
5: iconst_0
6: istore_2
7: iload_2
8: aload_1
9: arraylength
10: if_icmpge 34
13: getstatic #3 // Field logger:Ljava/util/logging/Logger;
16: getstatic #4 // Field java/util/logging/Level.WARNING:Ljava/util/logging/Level;
19: aload_1
20: iload_2
21: aaload
22: invokevirtual #5 // Method java/lang/StackTraceElement.getMethodName:()Ljava/lang/String;
25: invokevirtual #6 // Method java/util/logging/Logger.log:(Ljava/util/logging/Level;Ljava/lang/String;)V
28: iinc 2, 1
31: goto 7
34: return
public static void c(java.lang.Throwable);
Code:
0: aload_0
1: invokevirtual #2 // Method java/lang/Throwable.getStackTrace:()[Ljava/lang/StackTraceElement;
4: astore_1
5: aload_1
6: arraylength
7: istore_2
8: iconst_0
9: istore_3
10: iload_3
11: iload_2
12: if_icmpge 36
15: getstatic #3 // Field logger:Ljava/util/logging/Logger;
18: getstatic #4 // Field java/util/logging/Level.WARNING:Ljava/util/logging/Level;
21: aload_1
22: iload_3
23: aaload
24: invokevirtual #5 // Method java/lang/StackTraceElement.getMethodName:()Ljava/lang/String;
27: invokevirtual #6 // Method java/util/logging/Logger.log:(Ljava/util/logging/Level;Ljava/lang/String;)V
30: iinc 3, 1
33: goto 10
36: return
static {};
Code:
0: ldc #7 // String log
2: invokestatic #8 // Method java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger;
5: putstatic #3 // Field logger:Ljava/util/logging/Logger;
8: return
}
如您所见,a()
和c()
仅在variable assignment 处不同。 ,因此在 JVM 中的行为几乎相同,无论是否采用 JIT。 b()
略有不同:这里,arraylength
在循环中被调用。正如@thurstycrow 指出的那样,这不一定是性能问题,但也可能是。
因此,当涉及到实际性能时,您需要确定它是否值得考虑。检查堆栈跟踪的代码几乎永远不值得优化,因为您不希望一遍又一遍地获取堆栈跟踪。此外,我认为日志记录比数组长度检查要昂贵得多。
但是如果我们假设您遇到需要优化这段特定代码的情况,假设您正在编写一个自定义监控工具来检查所有抛出的异常,并且您希望它非常慢而不是非常慢(你看,收集堆栈跟踪是昂贵的;导航它通常非常便宜),你需要在野外测量它,因为 JIT 可以并且将考虑围绕此代码发生的一切出色地。
但这是一个无聊的答案,所以尽管我们知道这没有多大意义,但我们仍然可以做一些基准测试——毕竟我们可以,为什么不呢?您可以使用的一个很好的基准测试工具是 JMH ;你可以按照教程去玩它,或者只是捕获这个答案。
基准将是,
package org.sample;
import java.util.logging.*;
import java.util.*;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Scope;
@State(Scope.Thread)
public class ForLoop {
private static Logger logger = Logger.getLogger("log");
static {
logger.setLevel(Level.OFF);
}
private StackTraceElement elements[] = new Exception().getStackTrace();
@Benchmark
public void a0() {
for (int i = 0, n = elements.length; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
@Benchmark
public void a() {
for (int i = 0, n = elements.length; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
@Benchmark
public void b() {
for (int i = 0; i < elements.length; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
@Benchmark
public void c() {
int n = elements.length;
for (int i = 0; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
@Benchmark
public void d() {
for (StackTraceElement e: elements) {
logger.log(Level.WARNING, e.getMethodName());
}
}
@Benchmark
public void e() {
Arrays.stream(elements)
.forEach(item -> logger.log(Level.WARNING, item.getMethodName()));
}
}
(稍后将详细介绍 a0
;包含 for-each 和流的答案)。当我们运行它时,
alf-pro:test alf$ java -jar target/benchmarks.jar -wi 5 -i 5 -t 4 -f 1
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.a
# Run progress: 0.00% complete, ETA 00:01:00
# Fork: 1 of 1
# Warmup Iteration 1: 139092694.098 ops/s
# Warmup Iteration 2: 130833602.261 ops/s
# Warmup Iteration 3: 121355640.666 ops/s
# Warmup Iteration 4: 114037414.954 ops/s
# Warmup Iteration 5: 110355992.809 ops/s
Iteration 1: 111331613.966 ops/s
Iteration 2: 111401698.736 ops/s
Iteration 3: 108193438.523 ops/s
Iteration 4: 105277721.260 ops/s
Iteration 5: 103549199.780 ops/s
Result "a":
107950734.453 ±(99.9%) 13602765.938 ops/s [Average]
(min, avg, max) = (103549199.780, 107950734.453, 111401698.736), stdev = 3532595.117
CI (99.9%): [94347968.515, 121553500.391] (assumes normal distribution)
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.a0
# Run progress: 16.67% complete, ETA 00:00:51
# Fork: 1 of 1
# Warmup Iteration 1: 96143259.419 ops/s
# Warmup Iteration 2: 107561397.775 ops/s
# Warmup Iteration 3: 97488364.065 ops/s
# Warmup Iteration 4: 95880266.969 ops/s
# Warmup Iteration 5: 96943938.140 ops/s
Iteration 1: 95208831.922 ops/s
Iteration 2: 94012219.834 ops/s
Iteration 3: 95369199.325 ops/s
Iteration 4: 96090174.793 ops/s
Iteration 5: 90375159.036 ops/s
Result "a0":
94211116.982 ±(99.9%) 8743077.939 ops/s [Average]
(min, avg, max) = (90375159.036, 94211116.982, 96090174.793), stdev = 2270549.576
CI (99.9%): [85468039.043, 102954194.921] (assumes normal distribution)
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.b
# Run progress: 33.33% complete, ETA 00:00:41
# Fork: 1 of 1
# Warmup Iteration 1: 58778298.331 ops/s
# Warmup Iteration 2: 66786552.916 ops/s
# Warmup Iteration 3: 67834850.418 ops/s
# Warmup Iteration 4: 69421299.220 ops/s
# Warmup Iteration 5: 72392517.533 ops/s
Iteration 1: 70791625.464 ops/s
Iteration 2: 70393808.080 ops/s
Iteration 3: 68931230.026 ops/s
Iteration 4: 67113234.799 ops/s
Iteration 5: 71628641.383 ops/s
Result "b":
69771707.950 ±(99.9%) 6847578.759 ops/s [Average]
(min, avg, max) = (67113234.799, 69771707.950, 71628641.383), stdev = 1778294.458
CI (99.9%): [62924129.192, 76619286.709] (assumes normal distribution)
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.c
# Run progress: 50.00% complete, ETA 00:00:31
# Fork: 1 of 1
# Warmup Iteration 1: 87120233.617 ops/s
# Warmup Iteration 2: 88506588.802 ops/s
# Warmup Iteration 3: 82506886.728 ops/s
# Warmup Iteration 4: 75379852.092 ops/s
# Warmup Iteration 5: 83735974.951 ops/s
Iteration 1: 80107472.633 ops/s
Iteration 2: 85088925.886 ops/s
Iteration 3: 81051339.754 ops/s
Iteration 4: 85997882.597 ops/s
Iteration 5: 87092494.956 ops/s
Result "c":
83867623.165 ±(99.9%) 11946241.585 ops/s [Average]
(min, avg, max) = (80107472.633, 83867623.165, 87092494.956), stdev = 3102401.003
CI (99.9%): [71921381.580, 95813864.750] (assumes normal distribution)
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.d
# Run progress: 66.67% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration 1: 90916967.864 ops/s
# Warmup Iteration 2: 91629586.405 ops/s
# Warmup Iteration 3: 107866944.554 ops/s
# Warmup Iteration 4: 102023453.435 ops/s
# Warmup Iteration 5: 111336773.130 ops/s
Iteration 1: 107770637.269 ops/s
Iteration 2: 107103283.175 ops/s
Iteration 3: 107545862.850 ops/s
Iteration 4: 113804266.277 ops/s
Iteration 5: 114628060.965 ops/s
Result "d":
110170422.107 ±(99.9%) 14295432.924 ops/s [Average]
(min, avg, max) = (107103283.175, 110170422.107, 114628060.965), stdev = 3712478.533
CI (99.9%): [95874989.183, 124465855.031] (assumes normal distribution)
# JMH 1.13 (released 41 days ago)
# VM version: JDK 1.8.0, VM 25.0-b70
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.ForLoop.e
# Run progress: 83.33% complete, ETA 00:00:10
# Fork: 1 of 1
# Warmup Iteration 1: 33385239.816 ops/s
# Warmup Iteration 2: 38698292.771 ops/s
# Warmup Iteration 3: 38876327.513 ops/s
# Warmup Iteration 4: 37957299.742 ops/s
# Warmup Iteration 5: 39190117.656 ops/s
Iteration 1: 38286235.065 ops/s
Iteration 2: 39449652.416 ops/s
Iteration 3: 38541883.894 ops/s
Iteration 4: 40384962.473 ops/s
Iteration 5: 36975457.540 ops/s
Result "e":
38727638.278 ±(99.9%) 4934050.936 ops/s [Average]
(min, avg, max) = (36975457.540, 38727638.278, 40384962.473), stdev = 1281357.359
CI (99.9%): [33793587.342, 43661689.213] (assumes normal distribution)
# Run complete. Total time: 00:01:02
Benchmark Mode Cnt Score Error Units
ForLoop.a thrpt 5 107950734.453 ± 13602765.938 ops/s
ForLoop.a0 thrpt 5 94211116.982 ± 8743077.939 ops/s
ForLoop.b thrpt 5 69771707.950 ± 6847578.759 ops/s
ForLoop.c thrpt 5 83867623.165 ± 11946241.585 ops/s
ForLoop.d thrpt 5 110170422.107 ± 14295432.924 ops/s
ForLoop.e thrpt 5 38727638.278 ± 4934050.936 ops/s
我们可以看到这三种方法都非常快,以至于同一种方法在运行几次时会产生截然不同的测量结果。所以对于这个例子,我就到此为止。对于您的真实案例,请随意选择产生问题的实际代码。
PS. 添加了 for-each 和流解决方案。如您所见,for-each 几乎相同(但更具可读性);流明显变慢。我要离开 javap
examination将这两个解决方案作为读者的练习。
关于java - Java中的for循环优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39264844/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!