网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
为了更贴近现实,我已经用这种比较中的每种语言编写了一个 Web 服务。Web 服务非常简单,它为三个 REST http 服务。
Web 服务,使用 Java、Go 和 Rust。
github:https://github.com/dexterdarwich/ws-compare
文件大小
在 Java 打包构建的场景下下,我使用 maven-shade-plugin 将所有内容构建到一个 jar 中,并使用了 mvn package 打成 jar 包。在 Go 的情况下,我使用了go build. 最后,对于 Rust,我使用了cargo build --release.
每个程序的编译大小(以兆字节为单位)。
工程编译的大小还取决于所选的库/依赖项,在我的具体情况下,以上是编译后的程序大小。
在单独的部分中,我将构建所有三个程序并将其打包为 docker 映像,并将列出它们的大小以及显示每种语言所需的运行时开销。更多详情如下。
内存使用情况
没有任何请求的情况下
每个应用程序在内存中空闲时的内存使用情况。
Go 和 Rust 版本在空闲时显示内存占用几乎看不到,只是当 JVM 启动程序并闲置不做任何事情时,Java 消耗了 160 MB 以上的空间。在 Go 的情况下,程序使用 0.86 MB,在 Rust 的情况下使用 0.36 MB。这是一个很大的不同! 因为这是在内存中什么也不做情况下 ,Java 内存占用比 Go 和 Rust 对应物多两个数量级,所以这是对资源的巨大浪费。
REST 请求
让我们使用 wrk 通过请求访问 API 并观察内存和 CPU 使用情况,以及我的机器上针对程序的三个版本的每个请求地址请求的 qps。
wrk -t2 -c400 -d30s http://127.0.0.1:8080/hello
wrk -t2 -c400 -d30s http://127.0.0.1:8080/greeting/Jane
wrk -t2 -c400 -d30s http://127.0.0.1:8080/fibonacci/35
关于上面的 wrk 命令说如下,使用两个线程(用于 wrk)并在池中保持 400 个打开的连接,并在 30 秒的持续时间内重复调用 GET 请求。这里我只使用了两个线程,因为 wrk 和被测程序都在同一台机器上运行,所以我不希望它们在可用资源上(尤其是 CPU)相互竞争。
每个 Web 服务都分别进行了测试,并且在每次运行之间重新启动了 Web 服务。下面这个请求是该程序每个版本的三个运行中最好的一个。
/hello
此请求返回 Hello, World! 信息。它分配字符串“Hello, World!” 并将其序列化并以 JSON 格式返回。
请求 /hello 时的 CPU 使用率
访问 /hello 时的内存使用情况
访问 /hello qps
/greeting/{name}
此请求接受段路径参数 { name },然后格式化字符串“ Hello, {name}!” , 将其序列化并作为 JSON 格式的问候消息返回。
请求 /greeting/{name} 时的 CPU 使用率
访问 /greeting/{name} 时的内存使用情况
访问 /greeting/{name} qps
/fibonacci/{number}
此端点接受段路径参数 { number } 并返回斐波那契数和序列化为 JSON 格式的输入数字。
这个特定接口我选择以递归形式实现它。毫无疑问通过迭代实现会产生更好的性能结果,并且出于生产目的,应该选择迭代形式,但是在生产代码中存在必须使用递归的情况(不一定是专门用于计算第 n 个斐波那契数)。另外为了测试性能对比,通过该实现能够使大量 CPU 参与堆栈分配。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!