Golang 与 Java 的速度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51806224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:16:03  来源:igfitidea点击:

Speed of Golang Vs Java

javago

提问by ankur agrawal

I have written a program in Java and equivalent in Go. My java program is taking around 5.95 seconds to execute while Go program is taking around 41.675789791 seconds. While speed of Go is comparable to C or C++ as it is compiled like C then Why this much of performance difference exists? Programs are as follows:

我用 Java 编写了一个程序,用 Go 编写了一个等效的程序。我的 Java 程序执行时间约为 5.95 秒,而 Go 程序执行时间约为 41.675789791 秒。虽然 Go 的速度与 C 或 C++ 相当,因为它像 C 一样编译,但为什么会存在如此大的性能差异?程序如下:

Go Program

围棋程序

package main


import (
    "math"
    "fmt"
    "time"
)

func main() {
    fmt.Printf("vvalue is %v", testFun(10, 16666611, 1000000000))
}

func fun(x float64) float64 {
    return math.Pow(x, 2) - x
}

func testFun(first float64, second float64, times int) float64 {
    var i = 0
    var result float64 = 0
    var dx float64
    dx = (second - first) / float64(times)
    for ; i < times; i++ {
        result += fun(first + float64(i) * dx)
    }
    return result * dx
}   

Java Program

Java程序

public class Test {
public static void main(String[] args) {
    Test test = new Test();
    double re = test.testFun(10, 16666611, 1000000000);
    System.out.println(re);
}

private double testFun(double first, double second, long times) {
    int i = 0;
    double result = 0;
    double dx = (second - first) / times;
    for (; i < times; i++) {
        result += fun(first + i * dx);
    }
    return result * dx;
}

private double fun(double v) {
    return Math.pow(v, 2) - v;
}
}

回答by peterSO

Don't translate from another language. Write the Go version of your program in Go. For example, x*x - x,

不要从其他语言翻译。用 Go 编写程序的 Go 版本。例如x*x - x

package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    start := time.Now()
    v := testFun(10, 16666611, 1000000000)
    since := time.Since(start)
    fmt.Printf("value is %v\ntime is %v\n", v, since)
}

func fun(x float64) float64 {
    return x*x - x
}

func testFun(first float64, second float64, times int) float64 {
    sum := float64(0)
    dx := (second - first) / float64(times)
    for i := 0; i < times; i++ {
        sum += fun(first + float64(i)*dx)
    }
    return sum * dx
}

Output:

输出:

$ go version
go version devel +5c11480631 Fri Aug 10 20:02:31 2018 +0000 linux/amd64
$ go run speed.go
value is 1.543194272428967e+21
time is 1.011965238s
$

What results do you get?

你得到什么结果?

回答by Steffen Ullrich

I would suggest that math.Pow(x,y)in Go actually does x^ywithout any optimization for integer values of ywhile Math.pow(x,y)simply does x*xfor y==2. At least when replacing powwith a simple x*xin both programs I get 6.5 seconds for Java vs. 1.4 seconds for Go. Using powinstead I still get 6.5 seconds for Java while 29.4 seconds for Go.

我建议math.Pow(x,y)在 Go 中实际上没有x^yywhile 的整数值进行任何优化,而Math.pow(x,y)只是x*xfor y==2。至少在两个程序pow中用 simple替换时x*x,Java 为 6.5 秒,而 Go 为 1.4 秒。使用pow代替我仍然得到6.5秒为Java而29.4秒了围棋。

回答by Eric Wang

(With tips from above answers, I did more test, with an additional Cversion)

(根据上述答案的提示,我做了更多的测试,还有一个额外的C版本)

On my linux machine, with times = 100000000.

在我的 linux 机器上, times = 100000000

Testing result:

测试结果:

  • When exponent = 2.4
  • 当指数 = 2.4
 Java: result: 1.053906e+24, during: 7432 ms
    C: result: 1.053906e+24, during: 5544 ms
   Go: result: 1.053906e+24, during: 8.716807708s
 Java: result: 1.053906e+24, during: 7432 ms
    C: result: 1.053906e+24, during: 5544 ms
   Go: result: 1.053906e+24, during: 8.716807708s
  • When exponent = 2, still use pow()or Pow().
  • 当 exponent = 2 时,仍使用pow()or Pow()
 Java: result: 1.543194e+21, during: 630 ms
    C: result: 1.543194e+21, during: 852 ms
   Go: result: 1.543194e+21, during: 3.336549272s
 Java: result: 1.543194e+21, during: 630 ms
    C: result: 1.543194e+21, during: 852 ms
   Go: result: 1.543194e+21, during: 3.336549272s
  • When exponent = 2, but use x * xinstead.
  • 当 exponent = 2 时x * x改为使用。
 Java: result: 1.543194e+21, during: 636 ms
    C: result: 1.543194e+21, during: 340 ms
   Go: result: 1.543194e+21, during: 115.491272ms
 Java: result: 1.543194e+21, during: 636 ms
    C: result: 1.543194e+21, during: 340 ms
   Go: result: 1.543194e+21, during: 115.491272ms

Summary:

概括:

  • In general, gois really fast, according to the last test, faster than Java, or even C.
  • But, Javareally have a good pow()implementation, according to the first 2 test.
  • 一般来说,go真的很快,根据上次测试,比Java,甚至C
  • 但是,根据前 2 项测试,Java确实有一个很好的pow()实现。


Code

代码

Test.java:

测试.java:

/**
 * Compile:
 *  javac Test.java
 * Run:
 *  java Test
 */ 
public class Test {
    public static void main(String[] args) {
        Test test = new Test();
    long startAt = System.currentTimeMillis();
        double re = test.testFun(10, 16666611, 100000000);
    long during = System.currentTimeMillis() - startAt;
        System.out.printf("%10s: result: %e, during: %d ms\n", "Java", re, during);
    }

    private double testFun(double first, double second, long times) {
        int i = 0;
        double result = 0;
        double dx = (second - first) / times;
        for (; i < times; i++) {
            result += fun(first + i * dx);
        }
        return result * dx;
    }

    private double fun(double v) {
        return v * v - v;
        // return Math.pow(v, 2) - v;
        // return Math.pow(v, 2.4) - v;
    }
}

test.c:

测试.c:

/**
 * compile with:
 *  gcc test.c -lm
 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

double fun(double v) {
    return v * v - v;
    // return pow(v, 2) - v;
    // return pow(v, 2.4) - v;
}

double testFun(double first, double second, long times) {
    int i;
    double result = 0;
    double dx = (second - first) / times;
    for (i = 0; i < times; i++) {
        result += fun(first + i * dx);
    }
    return result * dx;
}

long long current_timestamp() {
    struct timeval te;
    gettimeofday(&te, NULL); // get current time
    long long milliseconds =
        te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds
    // printf("milliseconds: %lld\n", milliseconds);
    return milliseconds;
}

int main(int argc, char *argv[]) {
    long long startAt = current_timestamp();
    double re = testFun(10, 16666611, 100000000);
    long long during = current_timestamp() - startAt;
    printf("%10s: result: %e, during: %lld ms\n", "C", re, during);
    return 0;
}

test.go:

测试去:

/**
 * How to run:
 *  go run test.go
 */
package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    startAt := time.Now()
    result := testFun(10, 16666611, 100000000)
    during := time.Since(startAt)
    fmt.Printf("%10s: result: %e, during: %v\n", "Go", result, during)

    _ = math.Pow
}

func fun(x float64) float64 {
    return x*x - x
    // return math.Pow(x, 2) - x
    // return math.Pow(x, 2.4) - x
}

func testFun(first float64, second float64, times int) float64 {
    var i = 0
    var result float64 = 0
    var dx float64
    dx = (second - first) / float64(times)
    for ; i < times; i++ {
        result += fun(first + float64(i)*dx)
    }
    return result * dx
}

Compile:

编译:

javac Test.java; gcc test.c -lm; go build test.go

Run:

跑:

java Test; ./a.out ; ./test


@Update - C program with -O2or -O3option

@Update - 带有-O2-O3选项的C 程序

As suggested by Raffaelloin the comment, when compiling C program, could use -O2or -O3to further optimize the program.

正如Raffaello评论中所建议的,在编译 C 程序时,可以使用-O2-O3进一步优化程序。

And, following are the test result for Cprogram:

并且,以下是C程序的测试结果:

  • When exponent = 2.4.
  • 当指数 = 2.4 时
            C: result: 1.543194e+21, during: 5805 ms
 C with `-O2`: result: 1.543194e+21, during: 5324 ms
 C with `-O3`: result: 1.543194e+21, during: 5326 ms
            C: result: 1.543194e+21, during: 5805 ms
 C with `-O2`: result: 1.543194e+21, during: 5324 ms
 C with `-O3`: result: 1.543194e+21, during: 5326 ms
  • When exponent = 2, still use pow()or Pow().
  • 当 exponent = 2 时,仍使用pow()or Pow()
            C: result: 1.543194e+21, during: 897 ms
 C with `-O2`: result: 1.543194e+21, during: 119 ms
 C with `-O3`: result: 1.543194e+21, during: 121 ms
            C: result: 1.543194e+21, during: 897 ms
 C with `-O2`: result: 1.543194e+21, during: 119 ms
 C with `-O3`: result: 1.543194e+21, during: 121 ms
  • When exponent = 2, but use x * xinstead.
  • 当 exponent = 2 时x * x改为使用。
            C: result: 1.543194e+21, during: 353 ms
 C with `-O2`: result: 1.543194e+21, during: 122 ms
 C with `-O3`: result: 1.543194e+21, during: 119 ms
            C: result: 1.543194e+21, during: 353 ms
 C with `-O2`: result: 1.543194e+21, during: 122 ms
 C with `-O3`: result: 1.543194e+21, during: 119 ms

Summary- (-O2and -O3option):

摘要- (-O2-O3选项):

  • With -O2and -O3option
    • When base is integer (e.g 2), would make c program quicker, by several times.
    • When base is floating point number (e.g 2.4), it's also quicker, but very minimal.
  • Comparing between -O2and -O3, they are quite close in above tests.
  • -O2-O3选项
    • 当 base 为整数(例如 2)时,会使 c 程序更快,多次。
    • 当 base 是浮点数(例如 2.4)时,它也更快,但非常小。
  • -O2和之间进行比较-O3,它们在上述测试中非常接近。