Golang Vs Java的速度

Golang Vs Java的速度,java,go,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, 1000000

我已经用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
}   
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;
}
}
主程序包
进口(
“数学”
“fmt”
“时间”
)
func main(){
fmt.Printf(“v值为%v”,testFun(1016666111000000000))
}
func fun(x float64)float64{
返回math.Pow(x,2)-x
}
func testFun(第一个float64,第二个float64,乘以int)float64{
变量i=0
var结果float64=0
var dx浮点64
dx=(第二次-第一次)/float64(次)
对于;i<次;i++{
结果+=乐趣(第一次+64(i)*dx)
}
返回结果*dx
}   
Java程序

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
}   
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;
}
}
公共类测试{
公共静态void main(字符串[]args){
测试=新测试();
double re=test.testFun(101666611100000000);
系统输出打印项次(re);
}
私人双测试乐趣(双第一,双第二,长时间){
int i=0;
双结果=0;
双dx=(第二次-第一次)/次;
对于(;i<次;i++){
结果+=乐趣(第一个+i*dx);
}
返回结果*dx;
}
私人双乐(双v){
返回Math.pow(v,2)-v;
}
}

不要从其他语言翻译。在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
}

你得到了什么结果?

我建议,Go中的
math.Pow(x,y)
实际上没有对
y
的整数值进行任何优化,而
math.Pow(x,y)
只是对
y==2进行
x*x
。至少在这两个程序中,用简单的
x*x
替换
pow
时,Java和Go的时间分别为6.5秒和1.4秒。改用
pow
我仍然可以用Java获得6.5秒,用Go获得29.4秒。

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

在我的linux机器上,使用times=100000000

测试结果:

/**
 * 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;
    }
}
/**
 * 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;
}
/**
 * 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
}
javac Test.java; gcc test.c -lm; go build test.go
java Test; ./a.out ; ./test
  • 当指数=2.4时
  • 当exponent=2时,仍然使用
    pow()
    pow()
  • 当指数=2时,使用
    x*x
摘要:

/**
 * 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;
    }
}
/**
 * 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;
}
/**
 * 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
}
javac Test.java; gcc test.c -lm; go build test.go
java Test; ./a.out ; ./test
  • 一般来说,
    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;
    }
}
/**
 * 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;
}
/**
 * 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
}
javac Test.java; gcc test.c -lm; go build test.go
java Test; ./a.out ; ./test
跑步:

/**
 * 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;
    }
}
/**
 * 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;
}
/**
 * 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
}
javac Test.java; gcc test.c -lm; go build test.go
java Test; ./a.out ; ./test

@使用
-O2
-O3
选项更新-C程序 正如注释中的
Raffaello
所建议的,在编译C程序时,可以使用
-O2
-O3
进一步优化程序

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

  • 当指数=2.4
  • 当exponent=2时,仍然使用
    pow()
    pow()
  • 当指数=2时,使用
    x*x
摘要-(
-O2
-O3
选项):

  • 带有
    -O2
    -O3
    选项
    • 当基数为整数(例如2)时,会使c程序快几倍
    • 当基数是浮点数(例如2.4)时,速度更快,但非常小
  • 比较
    -O2
    -O3
    ,它们在上述测试中非常接近

Java使用JIT(实时)编译器进行优化,这意味着它将生成专门针对其运行的机器的机器代码,因此不要只认为Java很慢(er)。除非大部分程序的执行时间都花在计算指数上,否则这是一场白费力气的追逐。编写一个实际的程序,对其进行基准测试,分析找出热点,优化这些热点,重新运行基准测试,冲洗,重复。像这样的微基准点并不代表任何现实世界的场景。“不要从其他语言翻译”——很好的答案!这意味着在go中计算大整数n的x^n需要自己的幂函数实现,而不是使用数学。如果n不是浮点型,则Pow函数?对于这种示例,每种语言都是一样的。在该基准测试中,实际上是诚实地使用相同的“math.Pow”函数,而不是
x*x-x
表达式。所以这是不相关的,似乎
math.Pow()
在go中速度较慢,当Java和go都使用组件
2.4
时,go比Java慢一点,但当avoid
math.Pow()
时,go比Java快得多。这意味着在go中计算大整数n的x^n需要自己的幂函数实现,而不是使用math.Pow函数,如果n不是浮点类型?go会自动内联fun()并展开核心循环。Gcc可能是。显式使用C11内联、-O3和-funroll所有循环将加速C并提供更精确的比较。循环中由
dx
进行的乘法也可以用迭代加法代替。令人惊讶的是,C失去了一个用C编写的Go编译器。您应该使用
-o2
参数编译C代码以进行优化(甚至
-o3
)。如果更新的基准测试结果带有正确的C编译标志,那就太好了。:)@Raffaello感谢你的提示,事实上,
-O2
-O3
会加速上面的C程序,我已经用额外测试的结果更新了答案。顺便说一句,选项似乎应该是较高的
O
,而不是较低的。