问题描述
是否可能/合理地使用OpenJ9的class sharing功能来减少不同应用程序的单个实例的内存使用?
更多详细信息:
该功能似乎旨在减少在同一台计算机(例如Kubernetes节点)上运行同一应用程序的多个实例时的内存使用量。正确吗?
我想实现的是,巧合的是,在同一Kubernetes节点上启动的应用程序使用相同的缓存。由于应用程序使用几乎相同的库,因此应该可以共享大量数据。但是,我遇到的情况是,即使我使用了1GB的软限制和硬限制,缓存中的陈旧类的百分比也很高,甚至缓存已满100%。
具体来说,我尝试在同一Kubernetes节点上针对不同的部署使用java -Xshareclasses:cacheDir=/openj9cache,groupAccess,name=somename,nonfatal,persistent,verbose -XX:SharedCacheHardLimit=1g -Xscmx1g <APP>
。根据运行的应用程序,我会看到如下缓存统计信息:
cache layer = 0
cache size = 1073741216
softmx bytes = 1073741824
free bytes = 0
Reserved space for AOT bytes = -1
Maximum space for AOT bytes = -1
Reserved space for JIT data bytes = -1
Maximum space for JIT data bytes = -1
Metadata bytes = 937848376
Metadata % used = 87%
Class debug area size = 85868544
Class debug area used bytes = 4246022
Class debug area % used = 4%
ROMClass bytes = 36481772
AOT bytes = 12671632
JIT data bytes = 506596
Zip cache bytes = 0
Startup hint bytes = 360
Data bytes = 363936
# ROMClasses = 45685
# AOT Methods = 2997
# Classpaths = 30076
# URLs = 0
# Tokens = 0
# Zip caches = 0
# Startup hints = 3
# Stale classes = 40496
% Stale classes = 88%
Cache is 100% soft full
cache layer = 0
cache size = 1073741216
softmx bytes = 1073741824
free bytes = 0
Reserved space for AOT bytes = -1
Maximum space for AOT bytes = -1
Reserved space for JIT data bytes = -1
Maximum space for JIT data bytes = -1
Metadata bytes = 935010252
Metadata % used = 87%
Class debug area size = 85868544
Class debug area used bytes = 4745600
Class debug area % used = 5%
ROMClass bytes = 40151980
AOT bytes = 11919936
JIT data bytes = 426448
Zip cache bytes = 0
Startup hint bytes = 120
Data bytes = 363936
# ROMClasses = 38554
# AOT Methods = 2950
# Classpaths = 22680
# URLs = 0
# Tokens = 0
# Zip caches = 0
# Startup hints = 1
# Stale classes = 6354
% Stale classes = 16%
Cache is 100% soft full
base address = 0x00007F3D8C059000
end address = 0x00007F3DCC000000
allocation pointer = 0x00007F3D8F10BB80
cache layer = 0
cache size = 1073741216
softmx bytes = 1073741824
free bytes = 706740256
Reserved space for AOT bytes = -1
Maximum space for AOT bytes = -1
Reserved space for JIT data bytes = -1
Maximum space for JIT data bytes = -1
Metadata bytes = 199367772
Metadata % used = 54%
Class debug area size = 85868544
Class debug area used bytes = 6499570
Class debug area % used = 7%
ROMClass bytes = 51063680
AOT bytes = 29461056
JIT data bytes = 875612
Zip cache bytes = 0
Startup hint bytes = 360
Data bytes = 363936
# ROMClasses = 30778
# AOT Methods = 6624
# Classpaths = 8349
# URLs = 0
# Tokens = 0
# Zip caches = 0
# Startup hints = 3
# Stale classes = 3274
% Stale classes = 10%
Cache is 34% soft full
解决方法
最佳实践是对相同(或相似)应用程序的多个实例使用相同的共享缓存。如果您在不同的应用程序之间共享相同的缓存,则可能不会(最多)节省内存,因为共享的缓存包含其他应用程序存储的类,当前应用程序不需要这些类。
OpenJ9正在对类路径上的jar进行时间戳检查。它确保类路径上的类由于已存储到缓存中而没有更新,因此我们可以安全地将缓存的类返回给类加载器。找到更新后,原始的缓存类将标记为陈旧。
使用子选项“ bootClassesOnly”仅打开引导类的类共享。没有人在引导类路径上进行任何更新,因此您看不到任何陈旧的类。
我看到缓存统计信息中有数千个类路径。这些类路径上的内容是否已更新或在运行时生成?您可以使用-Xshareclasses子选项“ printStats = classpath”来显示所有类路径。如果您确定在运行之间没有更新类,则可以使用-Xshareclasses子选项“ noTimestampChecks”关闭时间戳检查。