作者:乃君敏睿64 | 来源:互联网 | 2022-12-07 06:19
最近一直在挑选Go,我是一个忠实的粉丝,来自Java背景.
我正在以不同的方式比较这些语言,并且惊讶于一个简单的循环计数高达200亿在Golang和Java中花了相当长的时间.
想知道是否有人可以提供任何见解,如果我在这里遗漏了什么.这就是我做的:
Java的
写下面的代码,从普通main()
方法执行它,用Gradle构建一个可执行jar,并使用以下命令从命令行执行它:java -jar build/libs/my-executable.jar
private void countToTwentyBillion() {
long count = 0;
long start = System.currentTimeMillis();
for (int k = 0; k <10; k++) {
System.out.println("On step " + k);
for (int i = 0; i <2_000_000_000; i++) {
// Do nothing but count
count++;
}
}
long end = System.currentTimeMillis();
System.out.println("Total time took: " + (end - start) + " ms to get at count: " + count);
}
在3个独立的试验中,我得到了以下结果:
// Total time took: 396 ms to get at count: 20000000000
// Total time took: 393 ms to get at count: 20000000000
// Total time took: 388 ms to get at count: 20000000000
// 392 ms average
走
在Go中构建此文件,使用"go build"构建它并在命令行执行 ./loop-counter
package main
import (
"fmt"
"time"
)
func main() {
count := 0
nanos := time.Now().UnixNano()
start := nanos / 1000000
for i := 0; i <10; i++ {
fmt.Printf("On step %d\n", i)
for k := 0; k <2000000000; k++ {
count++
}
}
nanos = time.Now().UnixNano()
end := nanos / 1000000
timeLength := end - start
fmt.Printf("Total time took: %d ms to get at count: %d\n", timeLength, count)
}
经过3次单独的试验,我得到了以下结果:
// Total time took: 5812 ms to get at count: 20000000000
// Total time took: 5834 ms to get at count: 20000000000
// Total time took: 5907 ms to get at count: 20000000000
// 5,851 ms average
我进入了这个期待Go更快,最终感到惊讶.所有试验均在相同条件下的同一台机器上进行.
任何人都可以说出什么给出
谢谢
1> lwi..:
我不是Go专家,但java确实优化了循环.
假设您有一个单核处理器3Ghz
,每条指令给出0.3ns,假设每个增量都是一条指令.所以0.3ns *20 bilion = 6s
是一个会粗略估计没有就地任何优化的性能.
您可以通过提供-XX:LoopUnrollLimit=1
给您的程序来验证java在这里做了些什么.这告诉JVM几乎不进行循环展开,因此可以防止大多数JIT优化在您的示例中发生.
这样做,你的java示例的运行时现在6s
在我的机器上,可与Go基准相媲美.
可能还有一个选项可以在Go版本中启用循环展开等优化(请参阅Go手册).
最后,这再次表明,基准测试很难实现.他们经常欺骗自己去做错误的事情.