dryeyhe0266 2018-08-22 01:20
浏览 140
已采纳

为什么在Go vs Java中运行这段代码要花费更长的时间

Been picking up Go recently and I'm a big fan, coming from a Java background.

I was comparing the languages in different ways, and was surprised that a simple loop counting up to 20 billion took substantially longer in Golang vs Java.

Was wondering if anyone can give any insight for if I'm missing something here. This is what I did:

Java

Wrote the below code, executed it from a normal main() method, built an executable jar with Gradle, and executed it from the command line with the command: 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);
}

Across 3 separate trials, I got these results:

// 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

Built this file in Go, built it with 'go build' and executed at the command line with ./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
", 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
", timeLength, count)

}

After 3 separate trials, I got these results:

// 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

I went into this expecting Go to be faster and ended up being surprised. All trials were done on the same machine with the same conditions.

Can anyone tell what gives?

Thanks

  • 写回答

2条回答 默认 最新

  • dongpa2000 2018-08-22 08:02
    关注

    I am not an Go expert but java is definitively optimizing the loop.

    Suppose you have a single core processor with 3Ghz, that gives you a 0.3ns per instruction, lets assume that every increment is one instruction. So 0.3ns *20 bilion = 6s is the performance one would roughly estimate without any optimizations in-place.

    You can verify that java does some trickery here by supplying -XX:LoopUnrollLimit=1 to your program. This tells the JVM to do almost no loop unrolling and therefore prevents most JIT optimizations from happening in your example.

    Doing that, the runtime of your java example is now 6s on my machine which is comparable to the Go benchmark.

    There is probably an option to enable optimizations like loop unrolling in the Go version as well (consult the Go manual for that).

    Finally, this shows again that micro benchmarks are tricky to get right. They often fool oneself in assuming things that are incorrect.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示