Golang Vs Java的速度
我已经用Java和Go编写了一个程序。我的java程序执行大约需要5.95秒,而Go程序执行大约需要41.675789791秒。虽然GO的速度与C或C++一样,因为它是编译成C的,那么为什么存在这么多的性能差异?计划如下: 围棋计划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
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慢一点,但当avoidmath.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
,而不是较低的。