Skip to content

Commit f80ebb8

Browse files
committed
[GR-17457] Move GC heap stats to a separate GC.heap_stats method
PullRequest: truffleruby/2691
2 parents 81e816f + 2032f7b commit f80ebb8

File tree

2 files changed

+88
-65
lines changed

2 files changed

+88
-65
lines changed

src/main/java/org/truffleruby/core/GCNodes.java

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -138,26 +138,22 @@ protected long time() {
138138
@Primitive(name = "gc_stat")
139139
public abstract static class GCStatPrimitiveNode extends PrimitiveArrayArgumentsNode {
140140

141-
@TruffleBoundary
142141
@Specialization
143-
protected RubyArray stat(
144-
@Cached StringNodes.MakeStringNode makeStringNode) {
142+
protected RubyArray stat() {
143+
final long[] data = getGCData();
144+
return createArray(data);
145+
}
146+
147+
@TruffleBoundary
148+
private long[] getGCData() {
145149
long time = 0;
146-
int count = 0;
147-
int minorCount = 0;
148-
int majorCount = 0;
149-
int unknownCount = 0;
150-
String[] memoryPoolNames = new String[0];
151-
Object[] memoryPools;
150+
long count = 0;
151+
long minorCount = 0;
152+
long majorCount = 0;
153+
long unknownCount = 0;
152154

153155
// Get GC time and counts from GarbageCollectorMXBean
154156
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
155-
// Get MemoryPoolName relevant to GC
156-
if (bean.getMemoryPoolNames().length > memoryPoolNames.length) {
157-
// Since old generation memory pools are a superset of young generation memory pools,
158-
// it suffices to check that we have the longer list of memory pools
159-
memoryPoolNames = bean.getMemoryPoolNames();
160-
}
161157
time += bean.getCollectionTime();
162158
count += bean.getCollectionCount();
163159
switch (bean.getName()) {
@@ -177,6 +173,43 @@ protected RubyArray stat(
177173
}
178174
}
179175

176+
final MemoryUsage total = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
177+
178+
return new long[]{
179+
time,
180+
count,
181+
minorCount,
182+
majorCount,
183+
unknownCount,
184+
total.getUsed(),
185+
total.getCommitted(),
186+
total.getInit(),
187+
total.getMax(),
188+
};
189+
}
190+
191+
}
192+
193+
@Primitive(name = "gc_heap_stats")
194+
public abstract static class GCHeapStatsNode extends PrimitiveArrayArgumentsNode {
195+
196+
@TruffleBoundary
197+
@Specialization
198+
protected RubyArray heapStats(
199+
@Cached StringNodes.MakeStringNode makeStringNode) {
200+
String[] memoryPoolNames = new String[0];
201+
Object[] memoryPools;
202+
203+
// Get GC time and counts from GarbageCollectorMXBean
204+
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
205+
// Get MemoryPoolName relevant to GC
206+
if (bean.getMemoryPoolNames().length > memoryPoolNames.length) {
207+
// Since old generation memory pools are a superset of young generation memory pools,
208+
// it suffices to check that we have the longer list of memory pools
209+
memoryPoolNames = bean.getMemoryPoolNames();
210+
}
211+
}
212+
180213
// Get memory usage values from relevant memory pools (2-3 / ~8 are relevant)
181214
memoryPools = new Object[memoryPoolNames.length];
182215
// On Native Image, ManagementFactory.getMemoryPoolMXBeans() is empty
@@ -190,33 +223,19 @@ protected RubyArray stat(
190223
}
191224
}
192225

193-
MemoryUsage total = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
194-
195226
Object[] memoryPoolNamesCast = new Object[memoryPoolNames.length];
196227
for (int i = 0; i < memoryPoolNames.length; i++) {
197228
memoryPoolNamesCast[i] = makeStringNode
198229
.executeMake(memoryPoolNames[i], UTF8Encoding.INSTANCE, CodeRange.CR_UNKNOWN);
199230
}
200231

201232

202-
return createArray(
203-
new Object[]{
204-
time,
205-
count,
206-
minorCount,
207-
majorCount,
208-
unknownCount,
209-
createArray(new long[]{
210-
total.getUsed(),
211-
total.getCommitted(),
212-
total.getInit(),
213-
total.getMax(),
214-
}),
215-
createArray(memoryPoolNamesCast),
216-
createArray(memoryPools) });
233+
return createArray(new Object[]{
234+
createArray(memoryPoolNamesCast),
235+
createArray(memoryPools) });
217236
}
218237

219-
protected RubyArray beanToArray(MemoryPoolMXBean bean) {
238+
private RubyArray beanToArray(MemoryPoolMXBean bean) {
220239
MemoryUsage usage = bean.getUsage();
221240
MemoryUsage peak = bean.getPeakUsage();
222241
MemoryUsage last = bean.getCollectionUsage();

src/main/ruby/truffleruby/core/gc.rb

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636

3737
module Truffle::GCOperations
3838
KNOWN_KEYS = %i[
39-
count
4039
time
40+
count
4141
minor_gc_count
4242
major_gc_count
4343
unknown_count
@@ -51,13 +51,12 @@ module Truffle::GCOperations
5151
]
5252

5353
def self.stat_hash(key = nil)
54-
time, count, minor_count, major_count, unknown_count, heap, memory_pool_names, memory_pool_info = Primitive.gc_stat
55-
used, committed, init, max = heap
54+
time, count, minor_count, major_count, unknown_count, used, committed, init, max = Primitive.gc_stat
5655

5756
# Initialize stat for statistics that come from memory pools, and populate it with some final stats (ordering similar to MRI)
5857
stat = {
59-
count: count,
6058
time: time,
59+
count: count,
6160
minor_gc_count: minor_count,
6261
major_gc_count: major_count,
6362
unknown_count: unknown_count, # if nonzero, major or minor count needs to be updated for this GC case
@@ -71,34 +70,6 @@ def self.stat_hash(key = nil)
7170
}
7271
stat.default = 0
7372

74-
unless Primitive.object_kind_of?(key, Symbol) # memory_pool_names are Strings
75-
memory_pool_names.each_with_index do |memory_pool_name, i|
76-
# Populate memory pool specific stats
77-
info = memory_pool_info[i]
78-
if info
79-
stat[memory_pool_name] = data = {
80-
used: info[0],
81-
committed: info[1],
82-
init: info[2],
83-
max: info[3],
84-
peak_used: info[4],
85-
peak_committed: info[5],
86-
peak_init: info[6],
87-
peak_max: info[7],
88-
last_used: info[8],
89-
last_committed: info[9],
90-
last_init: info[10],
91-
last_max: info[11],
92-
}
93-
94-
# Calculate stats across memory pools for peak_/last_ (we already know the values for current usage)
95-
data.each_pair do |k,v|
96-
stat[k] += v if k.start_with?('peak_', 'last_')
97-
end
98-
end
99-
end
100-
end
101-
10273
if key
10374
stat[key]
10475
else
@@ -160,6 +131,39 @@ def self.stat(key = nil)
160131
end
161132
end
162133

134+
def self.heap_stats
135+
memory_pool_names, memory_pool_info = Primitive.gc_heap_stats
136+
137+
stat = GC.stat
138+
memory_pool_names.each_with_index do |memory_pool_name, i|
139+
# Populate memory pool specific stats
140+
info = memory_pool_info[i]
141+
if info
142+
stat[memory_pool_name] = data = {
143+
used: info[0],
144+
committed: info[1],
145+
init: info[2],
146+
max: info[3],
147+
peak_used: info[4],
148+
peak_committed: info[5],
149+
peak_init: info[6],
150+
peak_max: info[7],
151+
last_used: info[8],
152+
last_committed: info[9],
153+
last_init: info[10],
154+
last_max: info[11],
155+
}
156+
157+
# Calculate stats across memory pools for peak_/last_ (we already know the values for current usage)
158+
data.each_pair do |k,v|
159+
stat[k] += v if k.start_with?('peak_', 'last_')
160+
end
161+
end
162+
end
163+
164+
stat
165+
end
166+
163167
module Profiler
164168
@enabled = true
165169
@since = 0

0 commit comments

Comments
 (0)