回复“666”获取独家整理的学习资料!java
前言
Java微服务能像Go微服务同样快吗?这是我最近一直在思索地一个问题。linux
去年8月份的the Oracle Groundbreakers Tour 2020 LATAM大会上,Mark Nelson和Peter Nagy就对此作过一系列基础的的测试用以比较。接下来就给你们介绍下。git
如下内容与观点主要源自 : https://medium.com/helidon/can-java-microservices-be-as-fast-as-go-5ceb9a45d673
在程序员圈子里,广泛的见解是Java老、慢、无聊 ,而Go是快、新、酷程序员
为了尽量的进行一个相对公平的测试,他们使用了一个很是简单的微服务,没有外部依赖关系(好比数据库),代码路径很是短(只是操纵字符串),使用了小型的、轻量级的框架(Helidon for Java和Go工具包for Go),试验了不一样版本的Java和不一样的jvm。github
对决双雄
咱们先来看下擂台两边的选手:算法
-
身穿深色战服的选手是 JAVA
Java是由被甲骨文收购的Sun Microsystems开发的。它的1.0版本是1996年发布的,最新的版本是2020年的Java15。主要的设计目标是Java虚拟机和字节码的可移植性,以及带有垃圾收集的内存管理。它是全世界最流行的语言之一,在开源环境下开发。数据库
咱们先看下JAVA的问题,你们广泛认为它最大的问题就是速度慢,已经慢到让人以为再也不是合理的,而是更具历史意义的。不过这么多年来,Java诞生了不少不一样的垃圾收集算法用来加快它运行的速度。微信
Oracle实验室最近已经开发了一个新的Java虚拟机GraalVM,它有一个新的编译器和一些使人兴奋的新特性,好比可以将Java字节码转换成一个本机映像,能够在没有javavm的状况下运行等。网络
-
而它的对手就是年轻充满活力的 GO
GO是由谷歌的罗伯特·格里默、罗伯·派克和肯·汤姆森建立的。他们对UNIX、B、C、Plan九、UNIX窗口系统等作出了重大贡献。GO是开源的,在2012年发布了1.0版本(比JAVA晚了16年),在2020年发布了1.15版本。不管是在采用方面,仍是在语言和工具生态系统自己方面,它都在快速增加。数据结构
GO受C、Python、JavaScript和C++等多种语言的影响。被设计成高性能网络和多处理的最佳语言。
StackOverflow有27872个关于Go的问题,而Java却有1702730个。足见长Java生态的强大。
Go是一种静态类型的编译语言。它有称为goroutines的轻量级进程(这些不是OS线程),它们之间有独特的通讯通道(类型化的,FIFO)。Go是许多CNCF项目的首选语言,例如Kubernetes、Istio、Prometheus和Grafana
赛前对比
从我的感受来讲,Go相比JAVA来讲,优势在于:
-
Go更容易实现复合、纯函数、不变状态等功能模式。 -
Go处于生命周期的早期,所以它没有向后兼容性的沉重负担—Go仍然能够轻易打破某些限制来改进。 -
Go编译成一个本机静态连接的二进制文件-没有虚拟机层-二进制文件拥有运行程序所需的一切,这对于“从头开始”的容器来讲很是好。 -
Go体积小、启动快、执行快(目前是的) -
Go没有OOP,继承,泛型,断言,指针算法 -
Go写法上较少的括号 -
Go没有循环依赖、没有未使用的变量或导入、没有隐式类型转换的强制 -
Go样板代码少得多
缺点是:
-
Go工具生态系统还不成熟,尤为是依赖关系管理——有几个选项,没有一个是完美的,特别是对于非开源开发;仍然存在兼容性挑战。 -
构建具备新的/更新的依赖项的代码很是慢(好比Maven著名的“下载Internet”问题) -
导入将代码绑定到存储库,这使得在存储库中移动代码成为一场噩梦。 -
调试、评测等仍然是一个挑战 -
用到了指针 -
须要实现一些基本的算法 -
没有动态连接 -
没有太多旋钮来调优执行或垃圾收集、概要文件执行或优化算法。
比赛开始
使用JMeter来运行负载测试。这些测试屡次调用这些服务,并收集有关响应时间、吞吐量(每秒事务数)和内存使用状况的数据。对于Go,收集驻留集大小;对于Java,跟踪本机内存。
在测量以前,使用1000次服务调用对应用程序进行预热。
应用程序自己的源代码以及负载测试的定义都在这个GitHub存储库中:https://github.com/markxnelson/go-java-go
第一回合
在第一轮测试中,在一台“小型”机器上进行了测试,是一台2.5GHz双核Intel core i7笔记本电脑,16GB内存运行macOS。测试运行了100个线程,每一个线程有10000个循环,上升时间为10秒。Java应用程序运行在JDK11和Helidon2.0.1上。使用Go 1.13.3编译的Go应用程序。
结果以下:

能够看出,第一回合是Go赢了!
JAVA占的内存太多了;预热对JVM有很大的影响—咱们知道JVM在运行时会进行优化,因此这是有意义的
在第一回合的基础上,意犹未尽的又引入GraalVM映像以使 Java 应用程序的执行环境更接近于 Go 应用程序的环境,添加了 GraalVM 映像测试(用 GraalVM EE 20.1.1ー JDK 11构建的本机映像)的结果是:
经过使用 GraalVM 映像在 JVM 上运行应用程序,咱们没有看到吞吐量或响应时间方面的任何实质性改进,可是内存占用的确变小了。
下面是一些测试的响应时间图:
第二回合
在第二轮测试中,使用一台更大的机器上运行测试。36核(每一个核两个线程)、256GB内存、运行oraclelinux7.8的机器。
和第一轮相似,使用了100个线程,每一个线程使用了10,000个循环,10秒的加速时间,以及相同版本的 Go,Java,Helidon 和 GraalVM。
结果以下:
这一回合是GraalVM 映像赢了!
下面是一些测试的响应时间图:


在这个测试中,Java变体的表现要好得多,而且在没有使用Java日志记录的状况下,它的性能大大超过了Go。Java彷佛更能使用硬件提供的多核和执行线程(与Go相比)。
这一轮的最佳表现来自GraalVM native image,平均响应时间为0.25毫秒,每秒事务数为82426个,而Go的最佳结果为1.59毫秒和39227个tps,然而这是以多占用两个数量级的内存为代价的!
GraalVM映像比在jvm上运行的同一应用程序快大约30–40%!
第三回合
此次,比赛在Kubernetes集群中运行这些应用程序,这是一个更天然的微服务运行时环境。
此次使用了一个Kubernetes 1.16.8集群,它有三个工做节点,每一个节点有两个内核(每一个内核有两个执行线程)、14GB的RAM和oraclelinux7.8。
应用程序访问是经过Traefik入口控制器进行的,JMeter在Kubernetes集群外运行,用于一些测试,而对于其余测试,使用ClusterIP并在集群中运行JMeter。
与前面的测试同样,使用了100个线程,每一个线程使用了10,000个循环,以及10秒的加速时间。
下面是各类不一样容器的大小:
-
Go 11.6MB 11.6 MB -
Java/Helidon 1.41GB 1.41 GB -
Java/Helidon JLinked 150MB 150mb -
Native image 25.2MB 25.2 MB
结果以下:
下面是一些测试的响应时间图:

在这一轮中,咱们观察到 Go 有时更快,GraalVM 映像有时更快,但这二者之间的差异很小(一般小于5%)。
Java彷佛比Go更善于使用全部可用的内核/线程—在Java测试中看到了更好的CPU利用率。Java性能在拥有更多内核和内存的机器上更好,Go性能在较小/功能较弱的机器上更好。在一台“生产规模”的机器上,Java很容易就和Go同样快,或者更快
最后
接下来会作更多的测试比赛,来看一看究竟谁更好!
有兴趣的你也能够本身试一试,记得告诉咱们结果哦!
昨晚逛GitHub,无心中看到一位大佬(https://github.com/halfrost
)的算法刷题笔记,感受发现了宝藏!有些小伙伴可能已经发现了,但咱这里仍是忍不住安利一波,怕有些小伙伴没有看到。
关于算法刷题的困惑和疑问也常常听朋友们说起。这份笔记里面共包含做者刷LeetCode算法题后整理的数百道题,每道题均附有详细题解过程。不少人表示刷数据结构和算法题效率不高,甚是痛苦。有了这个笔记的总结,对校招和社招的算法刷题帮助之大不言而喻,果断收藏了。





关注下方公众号
👇👇👇
回复关键字「刷题笔记」,便可下载
笔记版权归原做者全部,转载请注明出处 https://books.halfrost.com/leetcode/
本文分享自微信公众号 - 方志朋(walkingstory)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。