Golang与Java的速度

ank*_*wal 4 java go

我用Java编写了一个程序,并在Go中编写了相同的程序.我的java程序需要大约5.95秒执行,而Go程序大约需要41.675789791秒.虽然Go的速度与C或C++相当,因为它的编译方式与C类似,那么为什么存在这么大的性能差异呢?计划如下:

去节目

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
}   
Run Code Online (Sandbox Code Playgroud)

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;
}
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ang 11

(根据以上答案的提示,我做了更多测试,附加C版本)

在我的linux机器上,时间= 100000000.

测试结果:

  • 当指数= 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
Run Code Online (Sandbox Code Playgroud)
  • 当指数= 2时,仍然使用pow()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
Run Code Online (Sandbox Code Playgroud)
  • 当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
Run Code Online (Sandbox Code Playgroud)

摘要:

  • 总的来说,go根据最后一次测试,速度真的很快,Java甚至更快C.
  • 但是,根据前2个测试,Java确实有很好的pow()实现.

Test.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

test.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;
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

编译:

javac Test.java; gcc test.c -lm; go build test.go
Run Code Online (Sandbox Code Playgroud)

跑:

java Test; ./a.out ; ./test
Run Code Online (Sandbox Code Playgroud)

  • 您应该使用“-o2”参数编译 C 代码以进行优化(甚至“-o3”)。如果能获得带有正确 C 编译标志的更新基准测试结果,那就太好了。:) (2认同)
  • @Raffaello 感谢您的提示,确实“-O2”或“-O3”会加速上面的 C 程序,我已经用附加测试的结果更新了答案。顺便说一句,选项似乎应该是上面的“O”,而不是下面。 (2认同)

Ste*_*ich 6

我建议math.Pow(x,y)在Go中实际上x^y没有任何优化整数值,yMath.pow(x,y)只是x*x为了y==2.至少在两个程序pow中用简单替换时x*x,Java得到6.5秒而Go得到1.4秒.pow相反,我仍然使用Java获得6.5秒,而使用Go获得29.4秒.


pet*_*rSO 5

不要翻译另一种语言.在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
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ 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
$
Run Code Online (Sandbox Code Playgroud)

你得到了什么结果?

  • "不要翻译其他语言" - 很好的答案! (7认同)