前文是这个项目:果然吃内存,一个简单的 Java 程序就占用了 250M 内存
用 quarkus + graalvm 重新了这个项目(顺便学习了下 quarkus, 获益匪浅),功能逻辑全部保持了一致,只是组件根据框架进行了平移(比如 okhttp -> rest-client ).
程序的功能为:
这就是这个程序的所有功能,这版用到的组件和框架为 quarkus + gson + mybaits + jdbc + quarkus-rest-clint(发送网络请求) + jboss(quarkus 的默认日志)
编译环境:linux-x86-64, graalvm-21.(社区版),编译之后的二进制大小是 100M 。编译耗时大概十几分钟。 openjdk version "21.0.2" 2024-01-16 OpenJDK Runtime Environment GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30) OpenJDK 64-Bit Server VM GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30, mixed mode, sharing)
启动之后,占用 90M 内存,然后我调用了好几次 rest 请求,内存涨到了 120M ,过了一天程序稳定运行之后内存占用在 40-50M 左右。
虽然和我预期的 20M 内存有差距,但是已经比较满意了。虽然量起来了,内存占用一样会升高,但是没量了会把内存还给操作系统。quarkus 的启动速度确实快,毫秒级。
这次项目的意义,在于让我学会了 quarkus,(除了上面的项目,我还用 quarkus-picocli 写了个命令行工具,也很不错) 不愧是自古评论出人才。
此外,我用 python 实现了上面项目的核心部分,稳定之后内存占用 20M 。
最后,吹一下 quarkus, 在 native 这块很强,和 graalvm 的集成度非常高,比如反射问题单纯用 graalvm 需要繁琐的配置文件,在 quarkus 里面用一个注解就行了,方便很多。
缺点就是编译略慢,而且需要高配机器,配置越高,编译越快。
单纯的 graalvm 还是非常不行, 2024 年,graalvm native image 仍较为勉强 这个帖子也说了,但是和 quarkus 搭配一下就很不错了。
![]() |
1
GogoGo666 53 天前 ![]() 这种情况还是换 go 吧,不管是编译后的二进制大小,编译耗时,内存占用,都比 java 强太多了
|
2
yazinnnn0 53 天前 ![]() |
4
wssy001 53 天前 ![]() 无论是 springboot 还是 Quarkus 在改造成 Native Image 项目中 都会面临重构轮子的窘境
JVM 环境中,开发者 Google 到一个好轮子可以拿来直接用,而在 Native Image 中,开发者不得不考虑该怎么用原生的方式“曲线救国” 这是我这几年玩 GraalVM Native Image 的心得,最后得出一个结论:鉴于目前 Native Image 的生态,我觉得把项目用 go 重构的代价要比改成 Native Image 低不少(时间+精力方面) |
5
feiyan35488 53 天前
在意内存和制品大小的话,还考虑下 go 、rust 吧
缺硬件资源的企业不会用 java 的 |
6
zhaojun1998 53 天前
Spring Boot 改造现在已经还不错了,花了一周左右时间把一个 Spring Boot 2.6 (JDK1.8) 的项目,升级到 Spring Boot 3.3.0(JDK 21) Native 不算太麻烦,简单点说就是标记下哪些类用到了反射,要做 native 处理,如果库本身做了那你就不用做,如果没做,你自己添加到配置文件也行。
编译速度也做过测试,内存占的比重大于 CPU 性能,编译时可用内存最好 16+ 也不必谈 Java 色变,我觉得在这方面的努力这几年还是挺多的,估计过几年打包 native 就跟打包一个 jar 方便了。 不过缺点也有:编译速度慢,编译占用资源多,不支持交叉编译,社区不看好导致很多库不愿兼容 (我当时找兼容 flyway 时费了老大劲,后来发现还是 springboot 的工程师去兼容的,他们提交给 flyway 官方也不愿理睬) |
7
sunny352787 53 天前
用 go 写了个模拟,获取 baidu 首页然后插入 mongo ( upsert ),内存占用 2.9M ,rust 会不会是 k 级别?
|
![]() |
8
karottc OP @zhaojun1998 springboot 上,mybatis 加了配置文件也不行
|
![]() |
9
Goooooos 53 天前
正常程序员都会多种语言,不同场景选自己熟悉和合适的语言即可
1. 日常业务开发,我会用 Java 2. 导数据、数据分析,我用 python 3. 小组件,用 go 4. 前端,用 js 或 ts |
10
qq135449773 53 天前
其实有的时候解决 Java 的这种体积或者资源占用问题,最好的办法就是不用 Java
|
![]() |
11
javak 53 天前 via iPhone
我也不喜欢 go ,推荐学习下 rust ,大家都说好。我也觉得好(虽然我没用过)
|
![]() |
12
sagaxu 53 天前 ![]() @yazinnnn0 quarkus 用户基数太少了,我直接用的 vertx ,小版本常有大改动,遇到过不少问题,比如
redis client 超过 20 亿个请求之后 index 溢出; http server 某个版本 pause request 但 resume 处理不当,导致无法正常处理某些 HTTP 请求; redis 连接池连接泄漏; Templatehandler 找不到子目录下的模板; 这 4 个其中 3 个我提了 issue ,好在都很快解决了。 vertx 这玩意儿,不像 spring 家族那样可以无脑使用,但是用顺手了却非常舒适,即便出了问题,也很容易定位和解决,毕竟比 spring 全家桶简单太多了。 ===================================================================================== 这类小工具,用 Go 写也很舒服,graalvm build 几次的时间都够我用 Go 写完上线了 @zhaojun1998 我觉得 graalvm 的 native 要达到可用,还需要从预编译入手,发布 jar 的同时发布预编译文件,用户 build 时从预编译文件中提取组合,而不是把编译工作全部放在使用者的机器上做。解决了生态和资源消耗问题,可用性就起来了。这需要很长时间和很大存储空间,也不一定有足够多的资源投入。 |
13
kneo 53 天前 via Android
你喜欢就好。
|
![]() |
14
chendy 53 天前
羡慕楼主玩这么花还没人管
|
15
CodeCodeStudy 53 天前
我电脑 i7-6700 ,16G 内存,编译 hello,world 需要 34 秒,编译后的可执行文件是 6M 。
编译很久,连 graalvm 官方都出教程,编译完后怎么系统通知开发者 https://www.graalvm.org/latest/reference-manual/native-image/overview/Build-Overview/#getting-notified-when-the-build-process-is-done |
16
CodeCodeStudy 53 天前
我电脑 i7-6700 ,16G 内存,编译 hello,world 需要 34 秒,编译后的可执行文件是 6M 。
编译很久,连 graalvm 官方都出教程,编译完后怎么系统通知开发者 https://www.graalvm.org/latest/reference-manual/native-image/overview/Build-Overview/#getting-notified-when-the-build-process-is-done |
![]() |
17
luciankaltz 53 天前
我们之前某个小组件用 quarkus + native image 试了一下,结果发现有些莫名其妙的坑,比如上面说到的反射之类的。如果需要手动一个一个标注也太麻烦了(指没必要
说起来 quarkus 坑也很多就是了,还是不如 spring ( 一定要扣这些资源,不如直接用 go 重写就是了( |
18
INCerry 53 天前
|
19
artiga033 52 天前 via Android
@INCerry .NET AOT 这么多年了其实也就刚到勉强能用的阶段,性能折扣且不论,好多库还是不兼容 AOT 的,ASP.NET Core 还好,像桌面开发那边一大堆库都不兼容,因为大量使用反射,而且不说外部库,就是自己写代码,写 Source Generator 也比写反射折磨多了,论元编程能力个人感觉没有语言比得过 rust 。
Java 的 AOT 方案我不了解,不过感觉.NET 和 Java 这种感觉与其折腾预编译,不如考虑像 go 那样缩小 runtime 体积,但还是带一个 runtime 来做 gc 之类的。至少.NET AOT 直接就损失了大部分的运行时动态操作能力,而且 JIT 会对热点代码做高度优化,同一个函数调用次数越多性能越好,极有可能最终实际性能比 AOT 还高。 |
![]() |
20
janus77 52 天前
作为对比,你提到的 python 项目编译和启动速度如何
|
22
INCerry 52 天前
|
24
CodeCodeStudy 44 天前
编译十几分钟也太长了吧
|