graalvm 拯救了 Java 的启动速度,但没法拯救 Java 的内存占用

2024-01-04 15:34:20 +08:00
 keepRun

前几年,我一直期待 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 在解决内存占用问题上是不积极的。

17213 次点击
所在节点    程序员
137 条回复
keepRun
2024-01-04 17:26:44 +08:00
@qwertty01 这个就算了,这个只能临时用用
Richared
2024-01-04 17:27:58 +08:00
手写 servlet,能不用的包就别用,使用 Serial 。应该能省下不少。
keepRun
2024-01-04 17:30:07 +08:00
@abcbuzhiming 我也觉得,云厂商为了赚钱内存卖的比较贵,即便是如今内存价格已经降了很多的情况下
ddkk1112
2024-01-04 17:39:20 +08:00
@keepRun
不觉得你的想法很矛盾吗,一边说内存敏感,一边又要上 spring
你这不叫 java 应对内存敏感,而是 spring 内存占用测试
lambdaq
2024-01-04 17:40:36 +08:00
你跑起来只需要 200M ???我怎么感觉随便一个 java 项目不分配 2G 根本不敢上。。。
keepRun
2024-01-04 17:43:57 +08:00
@lambdaq 2g 有点夸张吧,你是依赖过多了吧,调整下最大堆内存大小,可以测试下最大堆内存调低到多少项目才无法启动
lambdaq
2024-01-04 17:49:36 +08:00
@keepRun 比如,线上 java 项目的 docker ,你敢不敢只分配 256MB 512MB 1G 就让跑。。。。
salmon5
2024-01-04 17:51:32 +08:00
确实 springboot 项目 JVM 2G-20G 不等。8G 的居多。
keepRun
2024-01-04 17:54:31 +08:00
@lambdaq 不敢,个人项目倒是可以
nothingistrue
2024-01-04 18:10:44 +08:00
不要嫌 Java 内存占用大,JVM 可是目前内存占用最小的 VM 。

相比与其他编码语言,Java 内存占用大,是因为 VM ,而决定 VM 的是 GC 机制,这都跟它的解释性运行架构没关系,所以编译成 native ,并不能减少内存占用。
morgan1freeman
2024-01-04 18:10:44 +08:00
@gitrebase #55 注意是量产工具,量产工具都是运行在 pc 上面的,内存? who care ? 就是 udp 通信,肯定启一个 springboot 然后 CommandLineRunner 里面 循环发送 udp 就完事了
yazinnnn0
2024-01-04 18:18:23 +08:00
怼上数据库(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
yazinnnn0
2024-01-04 18:19:48 +08:00
@yazinnnn0 #72 看起来 quarkus 给 20m 就可以跑个基本的 crud 程序了

话说在资源敏感的情况下, 不是该上 rust 吗?
yalin
2024-01-04 18:20:52 +08:00
k8s 容器环境的内存捉襟见肘
byte10
2024-01-04 18:28:19 +08:00
可以测试下 vert.x 吗, 这个估计占用也很小,几十 m
keepRun
2024-01-04 18:52:22 +08:00
@byte10 没用过,等个有缘人测试下
bjfane
2024-01-04 19:14:55 +08:00
graalvm 是不是没法用数据库连接池? 之前好像是。
keepRun
2024-01-04 19:23:30 +08:00
@bjfane 可以的,跟正常使用一样,graalvm 只是限制了反射和代理的使用,如果非要用到反射和代理,得通过 json 文件告知 graalvm
knightdf
2024-01-04 19:23:45 +08:00
反过来想,是 spring 不适合小项目,小项目就用 go rust
bjfane
2024-01-04 19:26:44 +08:00
@keepRun 谢谢,大概 10 个月之前折腾过一次,可能是 spring 或者连接池的原因,想弄成 native ,结果不行,就没深究了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1005841

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX