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

准备测试代码

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系统

  1. Java结果:3263111300 ns = 3263 ms = 3.2 s
  2. 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语言竟然性能如此之差,怎么受得了呢。那么为什么就改了一行代码,差距如此之大。

  1. Java结果:3263111300 ns = 3263 ms = 3.2 s
  2. 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通过做逃逸分析得出的,相信大家已经明白一些了,关于变量分配就说到这里,这个话题很深,可以聊很久,后面公众号会单独谈这个问题的,现在能说明白问题就行。

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

再有如果对Go的bubbleSort方法改为指针传递,如下,那么Go的执行性能又将如何,你可以试一试,留言区讨论。

func bubbleSort(arr *[]int) {
}

写在最后

抛开应用场景去谈性能都是耍流氓,每个语言都有自己的应用场景,有编译时,运行时的优化等,单单靠一个排序函数的结果探讨Java和Go的性能是错误的。网上也有很多实验来说明Go的性能是Java的好几倍,希望你见到时好好思考一下,这个测试是客观的吗?为什么会出现这个我意料之外的结果?

我看到的文章链接:https://studygolang.com/articles/25933

![](https://img2018.cnblogs.com/blog/706455/202001/706455-20200114131314944-608639848.jpg)

Go和Java的性能对比,真的如此吗?的更多相关文章

  1. java IO性能对比----read文件

    本次对比内容为:(jdk1.8) fileInputStream:最基本的文件读取(带自己声明的缓冲区) dataInputStream:字节读取,在<java编程思想>一书中描述为使用最 ...

  2. .Net Core 2.2与Java 12性能对比

    我发现基准游戏(https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/csharp.html)是一套非常好的基准测试. ...

  3. 【Java必修课】判断String是否包含子串的四种方法及性能对比

    1 简介 判断一个字符串是否包含某个特定子串是常见的场景,比如判断一篇文章是否包含敏感词汇.判断日志是否有ERROR信息等.本文将介绍四种方法并进行性能测试. 2 四种方法 2.1 JDK原生方法St ...

  4. 2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)

    2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不 ...

  5. mysql8 mongodb4 增删改查 性能对比,2019 最专业对比,nosql 真的比 sql 性能强很多?

    原文:mysql8 mongodb4 增删改查 性能对比,2019 最专业对比,nosql 真的比 sql 性能强很多? 版权所有:http://www.fengyunxiao.cn 近几年看了很多关 ...

  6. java中常见的json解析方法、库以及性能对比

    常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,json-lib. Gson(项目地址:https://githu ...

  7. 开发语言性能对比,C++、Java、Python、LUA、TCC

    一直想做开发语言性能对比,刚好有时间都做了给大家参考一下, 编译类:C++和Java表现还不错 脚本类:TCC脚本动态运行C语言,性能比其他脚本快好多... 想玩TCC的同学下载测试包,TCC目录下修 ...

  8. java数据库连接池性能对比

    这个测试的目的是验证当前常用数据库连接池的性能. testcase Connection conn = dataSource.getConnection(); PreparedStatement st ...

  9. [java]序列化框架性能对比(kryo、hessian、java、protostuff)

    序列化框架性能对比(kryo.hessian.java.protostuff) 简介:   优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...

随机推荐

  1. DOM事件和一些实用笔记

    let el = document.body.querySelector("style[type='text/css'], style:not([type])");返回HTML文档 ...

  2. iOS设备 微信h5页面回退 内容不刷新的问题

    原因分析: 一.android 浏览器 包括微信的开发者工具 都是ok的返回可以刷新页面但是唯有iOS不行. 二.iOS 浏览器原因:history.go(-1)返回上一页后,页面内容并不会刷新.在B ...

  3. poj 1787 Charlie's Change (多重背包可作完全背包)

    Charlie's Change Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3792   Accepted: 1144 ...

  4. 2008年NOIP普及组复赛题解

    题目涉及算法: ISBN号码:简单字符串模拟: 排座椅:贪心: 传球游戏:动态规划: 立体图:模拟. ISBN号码 题目链接:https://www.luogu.org/problem/P1055 简 ...

  5. Study in JI During the Summer Vacation

    15/07/2019-21/07/2019 Task List: 1.uow homework including vocabulary and listening 2.ASL's dictation ...

  6. JS正则验证两位小数,验证数字最简单正则表达式大全

    <h3>输入完按回车后即可验证!</h3> 正整数: <input type="text" size="20" onkeydown ...

  7. 浅谈集合框架二 List、Set常用方法

    最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...

  8. 查看php-fpm的进程和端口号

    ps -ef | grep php-fpm   查看php-fpm所有的进程 ps -ef | grep php-fpn.conf 查看配置所在路径 netstat -lntp 查看监听端口  lis ...

  9. vmware虚拟机卸载干净在注册表的也需要删除

  10. java打包上传服务器的一些命令

    Maven下package打包成jar包和war包,都在target目录下 其中War包扔在tomcat的webapps目录下.随tomcat启动自行启动 运行jar包命令. nohup java - ...