graalvm 拯救了 Java 的启动速度,但没法拯救 Java 的内存占用
source link: https://www.v2ex.com/t/1005841
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前几年,我一直期待 graalvm 把 java 编译成 native image 可以大幅减少 java 的内存占用,直到今天我用 graalvm 把我一个简单的 spring + spring mvc + mybatis plus + mysql 的小项目编译成 native 后(使用 g1gc ,配置最大堆内存 64m ),一测内存占用,好家伙,占用 184m ,优化了个寂寞,直接正常用 jvm 占用也就 200m 。启动速度确实快,285ms 即可完全启动。
我彻底死心了,java 对于请求量小的小型 web 项目内存消耗太大了,以后还是转投 nodejs 、golang 搞这种小项目吧,java 内存消耗太大了。
个人感觉云原生与微服务时代,java 官方对于资源占用问题解决速度还是太慢了,我阅读了 openjdk 社区的几乎所有的 jep ,发现起码未来 5 年,java 在解决内存占用问题上是不积极的。
keepRun 8 小时 12 分钟前 再提下官方进展:
官方在推进 java 使用值类型,这可以提高 java 执行效率(变量分配到栈上而不是堆,降低 gc 压力,提高 cpu 执行效率),推测由于逃逸分析更方便,一定程度上会降低一点内存占用,这个预计下一个 lts 会上线。 project leyden:探索渐进式约束 java 的动态特性换取更好的执行效率、性能占用、启动速度等问题,这个进度太慢了,起码得等到下下个 lts 。 其它的看过也忘了,基本上语法上不会有大的改动,优化主要在 jvm\gc 上,没太多亮点。 |
bthulu 8 小时 9 分钟前 内存从来都不是问题, 内存只会越来越便宜.
|
salmon5 8 小时 1 分钟前 小内存推荐 Serial GC...
|
kneo 7 小时 59 分钟前 再耐心一点,未来可期。
|
xiangyuecn 7 小时 55 分钟前 你的实际业务估计也就占用个 10-20M 内存,跟 java 本身关系不大,100M 内存也能跑很多业务+流量,就看你愿不愿意手撸 java 代码
|
keepRun 7 小时 51 分钟前 @xiangyuecn 手撸我还不如换成 golang 生态
|
StoneHuLu 7 小时 47 分钟前 我写 c#的 但我自己家里服务器部署的一些智能家居 api 我都用 golang 写的,镜像 17mb ,运行内存才几十 mb 不到,换 c#的镜像就得 250mb ,启动内存就得上百 mb
|
LykorisR 7 小时 46 分钟前 2 问题在于你用 spring 这种大型框架解决一个小问题,必然有大量的组件是无用占用
|
sephiroka 7 小时 46 分钟前 时间与空间不可兼得,更何况现在的内存便宜
|
lemonteacode 7 小时 44 分钟前 spring 本身就不是个小项目
|
icyalala 7 小时 40 分钟前 时间换空间:用你重写 go 的开发时间,换程序内存占用空间...
|
chendy 7 小时 38 分钟前 10 都上 spring 了,就别说省内存的事了…
如果真的内存敏感,试试隔壁 php 或者 go 或者 node 或者别的啥,一样的内存,java 可能应用都起不来他们可能还能顺便跑个 MySQL 啥场景用啥工具,用 java 干活说 java 吃内存,就好像说开大挂买菜说大挂废油一样… |
ChaYedan666 7 小时 35 分钟前 都用 spring 了。就别在乎内存了。
另外我一直不太懂,为什么要在小项目上追求启动速度 |
keepRun 7 小时 34 分钟前 @ChaYedan666 我这是测试,其实我是不在意其启动速度,但是云原生时代,启动速度快有很大的好处,对资源弹性伸缩比较好
|
INCerry 7 小时 32 分钟前 可以选择迁移到 C# .NET 上面,内存占用更低,也比迁移到 node.js go 这些更简单。
|
INCerry 7 小时 26 分钟前 |
wxyrrcj 7 小时 20 分钟前 solon
|
qwertty01 7 小时 16 分钟前 1 @keepRun #17 首先你要搞清楚 graalvm spring java 是三个东西。应该是用 spring 就别想降内存。你完全可以使用纯 java 写个 webserver ,然后到时候再来说用 java 就别想降内存
|
Lambdua 7 小时 13 分钟前 java 有轻量级的 web 框架吧,有尝试过吗
|
clorischan 7 小时 8 分钟前 |
INCerry 7 小时 6 分钟前 @keepRun go 才多少人用呀 拿互联网来说 一个公司能有多少个 go 岗位(我拿前司来说 中国互联网百强企业 写 go 一般都是基础设施组 就寥寥那么几个人专职写 go 除了某几个头铁的 都不会用 go 来写业务的) 另外编程又不止互联网
|
Plutooo 7 小时 5 分钟前 之前我跟 OP 也有同样的期待,那这么说的话 graalvm 除了启动速度方面还有什么大提升的地方
|
yazinnnn0 7 小时 5 分钟前 要不试试 quarkus?
docker run --cpus=0.1 --memory=20m --name quarkus -p 80:8080 yazi/sample:1.0 __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2024-01-04 08:46:58,037 INFO [io.quarkus] (main) sample 1.0 native (powered by Quarkus 3.6.4) started in 0.284s. Listening on: http://0.0.0.0:8080 2024-01-04 08:46:58,037 INFO [io.quarkus] (main) Profile prod activated. 2024-01-04 08:46:58,037 INFO [io.quarkus] (main) Installed features: [cdi, hibernate-orm, hibernate-reactive, kotlin, reactive-pg-client, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx] CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 185ccb037e19 quarkus 0.00% 12.16MiB / 20MiB 60.80% 993kB / 1.55MB 0B / 0B 42 yazinnnn0@cs-679368844937-default ~ [SIGINT]> wrk -t4 -d1s -c100 http://localhost:80/hello Running 1s test @ http://localhost:80/hello 4 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 127.19ms 114.59ms 430.17ms 55.63% Req/Sec 234.82 160.64 0.87k 78.57% 765 requests in 1.01s, 79.94KB read Requests/sec: 755.88 Transfer/sec: 78.98KB 简单试了下 demo, 容器可以给 20M 内存 |
hakr 7 小时 0 分钟前 你编译了多久........
|
Morii 6 小时 59 分钟前 使用 Spring 这种「企业级」的框架注定了无法轻量。为特定的场景做合适的技术选型是必修课。
|
ddkk1112 6 小时 58 分钟前 小型 web 项目用得着云原生 微服务吗
内存 1g 的轻量服务器不够你跑 springboot ? |
BBCCBB 6 小时 57 分钟前 这个内存占用和 java 无关, 大概率是 spring 等框架带来的占用.
你如果手撸 servlet, 占用也很低.. |
keepRun 6 小时 57 分钟前 1 @Plutooo 我目前只发现启动速度确实有很大优势,但是目前上手门槛还是太高了,且不说很多框架完全没有适配 graalvm ,我为了让 mybatis plus 能够不报错启动做了一大堆适配工作,github 看了不少讨论,在我看来起码还得 3 年 java 生态才能适配好 graalvm ,企业大规模采用的话应该要到 5 年后了。
graalvm 负面影响是牺牲了 java 的动态性,arthas 这种 debug 神器都没法用了 |
coinbase 6 小时 56 分钟前 golang 弱弱的来吊打一下 :)狗头
|
yolee599 6 小时 54 分钟前 是不是写 javaer 只会用 spring 全家桶啊?之前让同事帮忙写一个嵌入式的量产工具,需求是工人在 UI 填入设备序列号,通过 UDP 协议给设备,设备回复结果,超时就通过 UI 提示。等他交给我的时候启动日志就打印了一个大大的 SPRING
|
Cat7373 6 小时 47 分钟前 NodeJS + Koa + Knex 表示一个有几十个接口和十几张表,每分钟访问量大约一两百次的小项目大概需要 80M 内存
|
gitrebase 6 小时 37 分钟前 @yolee599 #50 只要不考虑内存什么的,现在写 Java 直接上 Spring Boot 完全没问题啊,Boot 提供了很多开箱即用的东西,没必要说“是不是写 javaer 只会用 spring 全家桶啊?”这种话吧;关于你的同事在“嵌入式”场景下用 Spring 这种重型 framework 可能确实不太妥,但我更倾向于这是使用者的问题
|
fuckshiter 6 小时 36 分钟前 我觉得这个得看业务跑起来之后的占用,不是看刚启动的
|
Cabana 6 小时 34 分钟前 要不试试 ktor?
|
abcbuzhiming 6 小时 32 分钟前 @bthulu 云上的内存其实非常有限,越是大企业越在意成本。
@ChaYedan666 越便宜的产品,消费者反而会越斤斤计较价格。总价 100w 的房子多 1w 少 1w 很多人不会有感觉,总价 10 块钱左右的拖鞋,很多人都会挑来跳去就为了省那一块钱 |
qwertty01 6 小时 30 分钟前 |
Richared 6 小时 27 分钟前 手写 servlet,能不用的包就别用,使用 Serial 。应该能省下不少。
|
keepRun 6 小时 25 分钟前 @abcbuzhiming 我也觉得,云厂商为了赚钱内存卖的比较贵,即便是如今内存价格已经降了很多的情况下
|
lambdaq 6 小时 14 分钟前 你跑起来只需要 200M ???我怎么感觉随便一个 java 项目不分配 2G 根本不敢上。。。
|
salmon5 6 小时 3 分钟前 确实 springboot 项目 JVM 2G-20G 不等。8G 的居多。
|
nothingistrue 5 小时 44 分钟前 不要嫌 Java 内存占用大,JVM 可是目前内存占用最小的 VM 。
相比与其他编码语言,Java 内存占用大,是因为 VM ,而决定 VM 的是 GC 机制,这都跟它的解释性运行架构没关系,所以编译成 native ,并不能减少内存占用。 |
morgan1freeman 5 小时 44 分钟前 @gitrebase #55 注意是量产工具,量产工具都是运行在 pc 上面的,内存? who care ? 就是 udp 通信,肯定启一个 springboot 然后 CommandLineRunner 里面 循环发送 udp 就完事了
|
yazinnnn0 5 小时 36 分钟前 怼上数据库(postgres)后简单模拟了一下 quarkus 在有限内存的情况
implementation("io.quarkus:quarkus-hibernate-reactive") implementation("io.quarkus:quarkus-resteasy-reactive-jackson") implementation("io.quarkus:quarkus-hibernate-reactive-panache-kotlin") implementation("io.quarkus:quarkus-kotlin") implementation("io.quarkus:quarkus-reactive-pg-client") @Entity class Todo : PanacheEntity() { companion object : PanacheCompanion<Todo> var title: String? = null var description: String? = null var completed: Boolean? = null @Column(name = "due_date") var dueDate: LocalDate? = null @Column(name = "created_at", updatable = false) var createdAt: LocalDate? = null @Column(name = "updated_at") var updatedAt: LocalDate? = null } @Path("todo") class TodoApi { @GET fun getAll() = Todo.listAll() @POST fun save(todo: Todo): Uni<Todo> { if (todo.id == null) { return todo.persistAndFlush<Todo>() } throw WebApplicationException("id shouldn't exist", 499) } @GET @Path("{id}") fun getOne(@RestPath id: Long) = Todo.findById(id) } version: '3.8' services: postgres: deploy: resources: limits: memory: 100m cpus: "0.1" image: postgres:latest environment: POSTGRES_DB: yazinnnn POSTGRES_USER: yazinnnn POSTGRES_PASSWORD: yazinnnn sample: image: yazi/sample:1.0 deploy: resources: limits: memory: 20m cpus: "0.1" ports: - "80:8080" depends_on: - postgres environment: "QUARKUS_DATASOURCE_REACTIVE_URL": vertx-reactive:postgresql://postgres/yazinnnn ➜ postgres wrk -t 12 -c 100 -d 10s http://localhost/todo 18:09:49 Running 10s test @ http://localhost/todo 12 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 536.18ms 143.86ms 999.36ms 75.14% Req/Sec 16.39 10.27 80.00 71.69% 1750 requests in 10.09s, 3.31MB read Requests/sec: 173.39 Transfer/sec: 335.78KB ➜ postgres wrk -t 12 -c 100 -d 10s http://localhost/todo/1 18:10:03 Running 10s test @ http://localhost/todo/1 12 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 256.09ms 78.20ms 499.31ms 84.83% Req/Sec 31.49 17.98 191.00 60.73% 3686 requests in 10.08s, 705.52KB read Requests/sec: 365.55 Transfer/sec: 69.97KB |
yalin 5 小时 34 分钟前 k8s 容器环境的内存捉襟见肘
|
byte10 5 小时 26 分钟前 可以测试下 vert.x 吗, 这个估计占用也很小,几十 m
|
bjfane 4 小时 40 分钟前 graalvm 是不是没法用数据库连接池? 之前好像是。
|
keepRun 4 小时 31 分钟前 via Android @bjfane 可以的,跟正常使用一样,graalvm 只是限制了反射和代理的使用,如果非要用到反射和代理,得通过 json 文件告知 graalvm
|
knightdf 4 小时 31 分钟前 反过来想,是 spring 不适合小项目,小项目就用 go rust
|
keepRun 4 小时 20 分钟前 @bjfane 可以看下这个项目,利用 spring 提供的 proxy 、reflect 钩子注册需要使用到代理、反射的地方,最终运行一个 native 程序
|
ufan0 3 小时 55 分钟前 遇到了一样的场景(使用 native 重构应用),虽然个人对这个结果是早有预见,但还是比较失落。
正在分别使用 quarkus 和 rust 重构,看看是否能带来内存和性能上的极大提升。 |
chaofanx 3 小时 52 分钟前 via Android quarkus 号称云原生 java
|
kenvix 3 小时 24 分钟前 你先把你的 spring 扔了用轻量框架再说; spring 自己就是个内存大户
|
buffzty 3 小时 15 分钟前 java 内存不是叫大 是非常大。一套 k8s 主节点所有服务才 1 个 G ,java 随便写点东西 2G 起步,不给多点 死给你看。
有得必有失,根据应用场景选,java 作为企业级大杀器 大厂有钱使劲造 稳定就行 |
itning 3 小时 12 分钟前 内存很值钱吗?
|
VYSE 2 小时 22 分钟前 JEB 加载个微信 APK, 得上 128G 内存
|
iseki 2 小时 12 分钟前 Graal 也没有魔法啊,能优化优化速度完全是仗着把初始化好的 heap 存起来了。春天包含这老多东西,那内存不可能小啊
|
cabing 56 分钟前 小项目使用 go 也很方便。
|
GeekGao 46 分钟前 早在 JDK 1.5 的时候我就觉得这内存吃不起啊,所以就玩起了 Python ,以及这两年的 Golang
|
90xchun 45 分钟前 via Android 内存使用和 graalvm 用不用关系不大,你自己 dump 下内存堆就可以了,spring 里面 jar 包太多了,native 后会直接被 graalvm 直接加载到内存里面,且一直不得释放,内存占用肯定下不来,小的 web 项目真没必要上 spring boot 全家桶,可以试试 https://github.com/94fzb/simplewebserver 这个库,内存 16m ,就启动的了,自己程序优化的好 32m ,就能流畅运行了
|
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK