提问人:Some Name 提问时间:11/17/2023 最后编辑:Some Name 更新时间:11/21/2023 访问量:37
为什么 System.gc() 用于并行,而 G1 则不减少 RSS?
Why isn't RSS reduced when System.gc() for parallel, but for G1 is?
问:
我正在使用 Java 17。我有一个 2GB 的容器并运行以下 Java 程序:
import java.util.*;
public class Main{
public static Map<byte[], byte[]> m = new HashMap<>();
public static void main(String args[]) throws Exception {
int i = 0;
while(true){
i++;
byte b[] = new byte[1024 * 1024];
m.put(b, b);
if(i % 700 == 0){
System.out.println("Reached limit: " + i);
m = new HashMap<>();
Thread.sleep(500000);
System.gc();
Thread.sleep(500000);
}
}
}
}
使用选项运行它
java -XX:+UseParallelGC \
-XX:InitialRAMPercentage=40 \
-XX:MaxRAMPercentage=40 \
-XX:-ShrinkHeapInSteps \
-XX:MinHeapFreeRatio=10 \
-XX:MaxHeapFreeRatio=10 Main
我一直收到堆报告的 RSS 是 800MB,它并没有变低。pmap
Address Perm Offset Device Inode Size Rss Pss Referenced Anonymous
ccc00000 rw-p 00000000 00:00 0 839680 838812 838812 838812 838812
但很明显,这是应用而不是忽略的:System.gc()
[5.871s][info ][gc ] GC(4) Pause Full (System.gc()) 702M->1M(792M) 2.820ms
所以既没有也没有减少RSS。-XX:-ShrinkHeapInSteps -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10 -XX:+UseParallelGC
System.gc()
我需要减少 RSS,因为大多数时候 Java 堆必须很小,而且白白消耗这么多 RSS 是低效的。
值得注意的是,可以减少 G1 GC 的 RSS 量并按预期工作。System.gc()
有没有办法为并行做到这一点,为什么 G1 和简单的完整 GC 需要是不够的?System.gc()
答:
1赞
apangin
11/21/2023
#1
并行 GC 从不取消提交为 Java 堆保留的内存,而 G1 可能会取消提交未使用的内存(即将其返回给操作系统)。在 JDK 12 之前,G1 只能在完整的 GC 或并发周期后返回内存。从 JDK 12 开始,它可以更频繁地取消提交 - 有关详细信息,请参见 JEP 346。
Смотритетакже: Java 进程的内存占用
评论
I need the RSS to be reduced since most of the time Java heap must be small and it's simply inefficient
我的观点恰恰相反。内存很便宜,工程时间很昂贵。你真的能证明这种说法的合理性吗?这里到底有什么效率低下?G1GC
System.gc()
java
1MB
800MB