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 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化