page contents

Golang和Java的性能对比,谁更好一目了然!

前两天我看到了一篇文章,测试Java和Go和Python的性能,其测试内容是一个排序,排序一亿次,然后看那个语言耗时最短,我先贴一下这个文章的测试结果,Java竟然比Go快了一倍不止,Go不是号称接...


attachments-2021-05-4yxKezBu60a3661e4004e.png

前两天我看到了一篇文章,测试Java和Go和Python的性能,其测试内容是一个排序,排序一亿次,然后看那个语言耗时最短,我先贴一下这个文章的测试结果,Java竟然比Go快了一倍不止,Go不是号称接近C的性能吗,难道?结尾我会把我看的这篇文章链接共享出来,接下来听我分析

attachments-2021-05-hW95VpaF60a3658a2455d.png

准备测试代码

Java测试代码

可以看的出来逻辑很简单,对一个固定数组排序,for循环执行一亿次,记录总的耗时时间,代码和我看过的文章代码一致。

public static void main(String[] args) {
    //记录开始时间
    long start = System.nanoTime();
    int num = 100000000;
    for (int i = 0; i < num; i++) {
        BubbleSort(1, 2, 3, 4, 5, 6, 7, 8, 9);
    }
    //打印耗时时间
    System.out.println(System.nanoTime() - start);
}
//排序
public static void BubbleSort(int... arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] < arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}


Go测试代码

和Java的功能是一样的,也是一亿次排序,代码和我看过的文章代码一致。

func Sort() {
   start := time.Now().UnixNano()
   var arr []int
   const NUM int = 100000000
   for i := 0; i < NUM; i++ {
      arr = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
      bubbleSort(arr)
   }
   //打印消耗时间
   fmt.Println(time.Now().UnixNano() - start)
}
//排序
func bubbleSort(arr []int) {
   for j := 0; j < len(arr)-1; j++ {
      for k := 0; k < len(arr)-1-j; k++ {
         if arr[k] < arr[k+1] {
            temp := arr[k]
            arr[k] = arr[k+1]
            arr[k+1] = temp
         }
      }
   }
}

我们分别执行以下这两段代码,看看结果到底多少呢,我的本地环境如下:

Java : jdk1.8,GoLang :1.12

i7处理器,16G内存,Windows10系统

Java结果:3263111300 ns = 3263 ms = 3.2 s

Go结果: 7165483700 ns = 7165 ms= 7.1 s

看到这个结果你信了吗? Java比Go的性能要好,快了一倍不止,我以前看到的文章难道都欺骗了我吗?


解密开始

仔细观察两段代码,其实是有一些细微区别的,有时候一点点的细微区别导致的结果千差万别,甚至让你得出一个错误结论从而误导你,看下面Go的代码,这个代码片段是在Sort方法中出现的,我们看到有一个arr变量,这个变量并没有在for循环中定义,而是在for循环外定义的,在for循环里面不断被重新赋值。

var arr []int
const NUM int = 100000000
for i := 0; i < NUM; i++ {
   arr = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
   bubbleSort(arr)
}

将上面的代码改成如下:

const NUM int = 100000000
for i := 0; i < NUM; i++ {
   arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
   bubbleSort(arr)
}

完成之后,我们再次测试,结果如下,这下心里稍微平衡一点了,要不然我一直热爱的Go语言竟然性能如此之差,怎么受得了呢。那么为什么就改了一行代码,差距如此之大。

Java结果:3263111300 ns = 3263 ms = 3.2 s

Go结果: 4137247700 ns = 4137 ms= 4.1 s

这其实涉及到Go的变量分配问题,Go内存分两种堆和栈,一个变量要么被分配在堆上,要么分配在栈上。

堆:由 GC 负责回收。对应于进程地址空间的堆

栈:不涉及 GC 操作。每个 goroutine 都有自己的栈,初始时被分配在进程地址空间的栈上,扩容时被分配在进程地址空间的堆上。

我们这里的arr变量是一个局部变量,那么到底Go将它分配在哪里呢?,我们对这两段代码做反编译分析,写一个main.go文件,在main函数中分别调用两个排序函数,然后执行这个命令:go tool compile -m main.go,得到结果如下,其中第一个圈红的是修改前的代码arr变量是被分配在堆上,修改后的代码arr变量是被分配在栈上,这是Go自主优化的,是怎么确定呢?Go通过做逃逸分析得出的,相信大家已经明白一些了,关于变量分配就说到这里,这个话题很深,可以聊很久,后面公众号会单独谈这个问题的,现在能说明白问题就行。

attachments-2021-05-SFtbBlaF60a366ca3c27c.png

事实上,如果你再深入一下,你对Java和Go的for循环次数调整一下,比如都调整为循环一千次,你再比较结果,你会发现Go的性能比Java的好,为什么呢?我提个醒,你可以从GC和Java的JIT优化方面思考一下。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-8lgx9oFL62ac11c6c6869.jpeg

  • 发表于 2021-05-18 15:06
  • 阅读 ( 621 )
  • 分类:Golang

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1474 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章