我用 Java 写了一个程序,用 Go 写了一个等价的程序。我的 java 程序执行大约需要 5.95 秒,而 Go 程序大约需要 41.675789791 秒。虽然 Go 的速度与 C 或 C++ 相当,因为它像 C 一样编译,但为什么存在如此大的性能差异?程序如下:
Go 程序
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 程序
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;
}
}
最佳答案
(根据上述答案的提示,我做了更多测试,并添加了一个 C
版本)
在我的 Linux 机器上,times = 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
- 当指数=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
- 当指数 = 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
总结:
- 总的来说,
go
真的很快,根据上次的测试,比Java
,甚至C
都快。 - 但是,根据前 2 个测试,
Java
确实有一个很好的pow()
实现。
代码
测试.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;
}
}
测试.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;
}
测试.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
}
编译:
javac Test.java; gcc test.c -lm; go build test.go
运行:
java Test; ./a.out ; ./test
@Update - 带有-O2
或-O3
选项的C 程序
Raffaello
在评论中建议,在编译C程序时,可以使用-O2
或-O3
来进一步优化程序。
C
程序的测试结果如下:
- 当指数 = 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
- 当指数=2时,仍然使用
pow()
或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
- 当指数 = 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
总结 -(-O2
和-O3
选项):
- 带有
-O2
和-O3
选项- 当基数是整数(例如 2) 时,将使 c 程序更快,快几倍。
- 当基数是 float 时(例如 2.4),它也更快,但非常小。
- 比较
-O2
和-O3
,它们在上述测试中非常接近。
关于java - Golang 与 Java 的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51806224/