Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_trace/TgcHeap.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2019 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "j9.h"
24
#include "j9cfg.h"
25
#include "mmhook.h"
26
#include "j9port.h"
27
#include "modronopt.h"
28
#include "j9comp.h"
29
30
#include "GCExtensions.hpp"
31
#include "Heap.hpp"
32
#include "HeapStats.hpp"
33
#include "TgcExtensions.hpp"
34
#include "TgcHeap.hpp"
35
#include "Heap.hpp"
36
#include "MemorySpace.hpp"
37
#include "MemorySubSpace.hpp"
38
#include "MemoryPool.hpp"
39
#include "ParallelSweepChunk.hpp"
40
#include "SweepHeapSectioning.hpp"
41
#include "ModronAssertions.h"
42
43
#include "SweepStats.hpp"
44
#include "GlobalGCStats.hpp"
45
46
47
#include "j9.h"
48
#include "j9cfg.h"
49
#include "mmhook.h"
50
#include "j9port.h"
51
#include "modronopt.h"
52
#include "j9comp.h"
53
54
#include "FreeHeapRegionList.hpp"
55
#include "GCExtensions.hpp"
56
#include "GlobalAllocationManagerSegregated.hpp"
57
#include "GlobalGCStats.hpp"
58
#include "Heap.hpp"
59
#include "HeapRegionQueue.hpp"
60
#include "LockingHeapRegionQueue.hpp"
61
#include "MemoryPool.hpp"
62
#include "MemorySpace.hpp"
63
#include "MemorySubSpace.hpp"
64
#include "ParallelSweepChunk.hpp"
65
#include "RegionPoolSegregated.hpp"
66
#include "SegregatedAllocationInterface.hpp"
67
#include "SweepHeapSectioning.hpp"
68
#include "SweepStats.hpp"
69
#include "TgcExtensions.hpp"
70
#include "TgcHeap.hpp"
71
72
#include "MemoryPool.hpp"
73
74
static void
75
tgcHeapPrintStats(OMR_VMThread* omrVMThread)
76
{
77
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);
78
79
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
80
MM_HeapStats stats;
81
MM_Heap *heap = extensions->heap;
82
/* Gather statistics on all allocations since last collection from memory pools */
83
heap->mergeHeapStats(&stats); /* Assume active */
84
85
tgcExtensions->printf("------------- Heap Statistics -------------\n");
86
tgcExtensions->printf("Heap Allocated Count: %12zu\n", stats._allocCount);
87
tgcExtensions->printf("Heap Allocated Bytes: %12zu\n", stats._allocBytes);
88
tgcExtensions->printf("Heap Discarded Bytes: %12zu\n", stats._allocDiscardedBytes);
89
tgcExtensions->printf("Heap Search Count: %12zu\n", stats._allocSearchCount);
90
tgcExtensions->printf("Heap Free After Last GC: %12zu\n", stats._lastFreeBytes);
91
tgcExtensions->printf("Freelist Size: %12zu\n", stats._activeFreeEntryCount);
92
tgcExtensions->printf("Deferred Size: %12zu\n", stats._inactiveFreeEntryCount);
93
}
94
95
static void
96
tgcHeapMicroFragmentPrintStats(OMR_VMThread* omrVMThread)
97
{
98
void *tgcRegionDarkmatter_address_start = NULL;
99
void *tgcRegionDarkmatter_address_end = NULL;
100
UDATA tgcRegionDarkmatter_bytes = 0;
101
UDATA tgcRegionFree_bytes = 0;
102
UDATA tgcRegionDarkmatter_count = 0;
103
const UDATA tgcRegionMaxcount = 20;
104
105
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);
106
107
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
108
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
109
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
110
111
UDATA totalChunkCount = extensions->splitFreeListNumberChunksPrepared;
112
UDATA tgcRegionDarkmatter_size = totalChunkCount/tgcRegionMaxcount; /**> number of chunks */
113
114
if (0 == tgcRegionDarkmatter_size) {
115
tgcRegionDarkmatter_size = 1;
116
}
117
118
MM_ParallelSweepChunk* sweepChunk = NULL;
119
MM_ParallelSweepChunk* lastSweepChunk = NULL;
120
MM_SweepHeapSectioningIterator sectioningIterator(extensions->sweepHeapSectioning);
121
UDATA regionSize = 0;
122
123
OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);
124
char timestamp[32];
125
omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());
126
tgcExtensions->printf("------- Micro Fragment Statistics timestamp=\"%s\" ---------\n", timestamp);
127
tgcExtensions->printf(" address start - address end ( size) free KBytes( Pct) fragment KBytes( Pct)\n");
128
129
for (uintptr_t chunkNum = 0; chunkNum < totalChunkCount; chunkNum++) {
130
sweepChunk = sectioningIterator.nextChunk();
131
if (MEMORY_TYPE_OLD == sweepChunk->memoryPool->getSubSpace()->getTypeFlags()) {
132
133
if (0 == sweepChunk->chunkTop) {
134
continue;
135
}
136
tgcRegionDarkmatter_count += 1;
137
tgcRegionDarkmatter_bytes += sweepChunk->_darkMatterBytes;
138
tgcRegionFree_bytes += sweepChunk->freeBytes;
139
lastSweepChunk = sweepChunk;
140
if (1 == tgcRegionDarkmatter_count) {
141
tgcRegionDarkmatter_address_start = sweepChunk->chunkBase;
142
}
143
if (tgcRegionDarkmatter_size == tgcRegionDarkmatter_count) {
144
tgcRegionDarkmatter_address_end = sweepChunk->chunkTop;
145
if (tgcRegionDarkmatter_address_end == tgcRegionDarkmatter_address_start) {
146
break;
147
}
148
regionSize = (UDATA)tgcRegionDarkmatter_address_end-(UDATA)tgcRegionDarkmatter_address_start;
149
150
tgcExtensions->printf("%p - %p(%3zuMB)%14zuKB(%5.2f%%)%14zuKB(%5.2f%%)\n",
151
tgcRegionDarkmatter_address_start, tgcRegionDarkmatter_address_end, regionSize>>20,
152
tgcRegionFree_bytes >> 10, 100 * (float)tgcRegionFree_bytes/(float)regionSize,
153
tgcRegionDarkmatter_bytes >> 10, 100 * (float)tgcRegionDarkmatter_bytes/(float)regionSize);
154
155
tgcRegionDarkmatter_count = 0;
156
tgcRegionDarkmatter_bytes = 0;
157
tgcRegionFree_bytes = 0;
158
}
159
}
160
}
161
162
if (0 != tgcRegionDarkmatter_count) {
163
tgcRegionDarkmatter_address_end = lastSweepChunk->chunkTop;
164
regionSize = (UDATA)tgcRegionDarkmatter_address_end-(UDATA)tgcRegionDarkmatter_address_start;
165
166
tgcExtensions->printf("%p - %p(%3zuMB)%14zuKB(%5.2f%%)%14zuKB(%5.2f%%)\n",
167
tgcRegionDarkmatter_address_start, tgcRegionDarkmatter_address_end, regionSize>>20,
168
tgcRegionFree_bytes >> 10, 100 * (float)tgcRegionFree_bytes/(float)regionSize,
169
tgcRegionDarkmatter_bytes >> 10, 100 * (float)tgcRegionDarkmatter_bytes/(float)regionSize);
170
171
tgcRegionDarkmatter_count = 0;
172
tgcRegionDarkmatter_bytes = 0;
173
tgcRegionFree_bytes = 0;
174
}
175
UDATA tenureDarkMatterBytes = tenureMemorySubspace->getMemoryPool()->getDarkMatterBytes();
176
UDATA tenureFreeBytes = tenureMemorySubspace->getMemoryPool()->getApproximateFreeMemorySize();
177
178
tgcExtensions->printf("Tenure(%zuMB) Free Size: %12zu(%zuMB, %5.2f%%), Micro Fragment Size: %12zu(%zuMB, %5.2f%%)\n",
179
extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD)>>20, tenureFreeBytes, tenureFreeBytes>>20, 100 * (float)tenureFreeBytes / (float)extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD),
180
tenureDarkMatterBytes, tenureDarkMatterBytes>>20, 100 * (float)tenureDarkMatterBytes / (float)extensions->heap->getActiveMemorySize(MEMORY_TYPE_OLD));
181
182
MM_SweepStats *sweepStats = &extensions->globalGCStats.sweepStats;
183
184
U_64 duration = omrtime_hires_delta(sweepStats->_startTime, sweepStats->_endTime, J9PORT_TIME_DELTA_IN_MICROSECONDS);
185
tgcExtensions->printf("Sweep Time(ms): total=\"%llu.%03.3llu\", DarkMatter Samples: %zu\n",
186
duration / 1000, duration % 1000, tenureMemorySubspace->getMemoryPool()->getDarkMatterSamples());
187
188
}
189
190
static void
191
tgcHookHeapGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
192
{
193
MM_GlobalGCStartEvent* event = (MM_GlobalGCStartEvent*)eventData;
194
tgcHeapPrintStats(event->currentThread);
195
}
196
197
static void
198
tgcHookHeapLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
199
{
200
MM_LocalGCStartEvent* event = (MM_LocalGCStartEvent*)eventData;
201
tgcHeapPrintStats(event->currentThread);
202
}
203
204
static void
205
tgcHookGlobalGcSweepEndPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
206
{
207
MM_SweepEndEvent* event = (MM_SweepEndEvent*)eventData;
208
tgcHeapMicroFragmentPrintStats(event->currentThread);
209
}
210
211
#if defined(J9VM_GC_SEGREGATED_HEAP)
212
static void
213
tgcShowRegions(OMR_VMThread *omrVMThread, const char *comment)
214
{
215
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);
216
MM_GCExtensionsBase *extensions = MM_GCExtensions::getExtensions(omrVMThread);
217
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);
218
219
MM_GlobalAllocationManagerSegregated *globalAllocationManager = (MM_GlobalAllocationManagerSegregated *) extensions->globalAllocationManager;
220
MM_RegionPoolSegregated *regionPool = globalAllocationManager->getRegionPool();
221
222
globalAllocationManager->flushCachedFullRegions(env);
223
224
uintptr_t countSmall, countLarge, countArraylet, countFree, countCoalesce, countMultiFree;
225
uintptr_t countTotal = 0;
226
uintptr_t countFullSmallTotal = 0;
227
uintptr_t countAvailableSmallTotal = 0;
228
uintptr_t darkMatterBytesTotal = 0;
229
uintptr_t allocCacheBytesTotal = 0;
230
231
tgcExtensions->printf(">>> %32s \n", comment);
232
tgcExtensions->printf(">>> sizeClass | full | available | total | dark | cache\n");
233
tgcExtensions->printf(">>> ====================================================================\n");
234
uintptr_t regionSize = extensions->heap->getHeapRegionManager()->getRegionSize();
235
236
for (int32_t sizeClass = OMR_SIZECLASSES_MIN_SMALL; sizeClass <= OMR_SIZECLASSES_MAX_SMALL; sizeClass++) {
237
uintptr_t cellSize = env->getExtensions()->defaultSizeClasses->getCellSize(sizeClass);
238
countSmall= regionPool->getSmallFullRegions(sizeClass)->getTotalRegions();
239
countFullSmallTotal += countSmall;
240
tgcExtensions->printf(">>> %2d: %5d | %4d | ", sizeClass, cellSize, countSmall);
241
242
for (int32_t i = 0; i < NUM_DEFRAG_BUCKETS; i++) {
243
uintptr_t count = 0;
244
for (uintptr_t j = 0; j < regionPool->getSplitAvailableListSplitCount(); j++) {
245
count += regionPool->getSmallAvailableRegions(sizeClass, i, j)->getTotalRegions();
246
}
247
countSmall += count;
248
countAvailableSmallTotal += count;
249
tgcExtensions->printf(" %4d ", count);
250
}
251
countTotal += countSmall;
252
tgcExtensions->printf("| %5d | ", countSmall);
253
254
uintptr_t darkMatterBytes = regionPool->getDarkMatterCellCount(sizeClass) * cellSize;
255
darkMatterBytesTotal += darkMatterBytes;
256
tgcExtensions->printf("%6.2f%% | ", (countSmall == 0)? 0: (darkMatterBytes / (countSmall * regionSize)));
257
258
uintptr_t allocCacheSize = 0;
259
GC_OMRVMThreadListIterator vmThreadListIterator(env->getOmrVM());
260
while(OMR_VMThread* thread = vmThreadListIterator.nextOMRVMThread()) {
261
MM_EnvironmentBase *envThread = MM_EnvironmentBase::getEnvironment(thread);
262
allocCacheSize += MM_SegregatedAllocationInterface::getObjectAllocationInterface(envThread)->getAllocatableSize(sizeClass);
263
}
264
265
allocCacheBytesTotal += allocCacheSize;
266
tgcExtensions->printf("%5d\n", allocCacheSize);
267
}
268
269
tgcExtensions->printf(">>> region size %d\n", regionSize);
270
271
uintptr_t arrayletLeafSize = extensions->getOmrVM()->_arrayletLeafSize;
272
tgcExtensions->printf(">>> arraylet leaf size %d\n", arrayletLeafSize);
273
274
tgcExtensions->printf(">>> small total (full, available) region count %d (%d, %d)\n", countTotal, countFullSmallTotal, countAvailableSmallTotal);
275
276
countTotal += countLarge = regionPool->getLargeFullRegions()->getTotalRegions();
277
tgcExtensions->printf(">>> large full region count %d\n", countLarge);
278
279
countTotal += countArraylet = regionPool->getArrayletFullRegions()->getTotalRegions();
280
tgcExtensions->printf(">>> arraylet full region count %d\n", countArraylet);
281
282
countTotal += (countArraylet = regionPool->getArrayletAvailableRegions()->getTotalRegions());
283
tgcExtensions->printf(">>> arraylet available region count %d\n", countArraylet);
284
285
countTotal += countFree = regionPool->getSingleFreeList()->getTotalRegions();
286
tgcExtensions->printf(">>> free region count %d\n", countFree);
287
288
countTotal += countMultiFree = regionPool->getMultiFreeList()->getTotalRegions();
289
tgcExtensions->printf(">>> mutliFree region count %d\n", countMultiFree);
290
291
countTotal += countCoalesce = regionPool->getCoalesceFreeList()->getTotalRegions();
292
tgcExtensions->printf(">>> coalesce region count %d\n", countCoalesce);
293
294
uintptr_t heapSize = countTotal * env->getExtensions()->getHeap()->getHeapRegionManager()->getRegionSize();
295
296
tgcExtensions->printf(">>> total region count %d\n", countTotal);
297
tgcExtensions->printf(">>> dark matter total bytes %d (%2.2f%% of heap)\n", darkMatterBytesTotal, 100.0 * darkMatterBytesTotal / heapSize);
298
tgcExtensions->printf(">>> allocation cache total bytes %d (%2.2f%% of heap)\n", allocCacheBytesTotal, 100.0 * allocCacheBytesTotal / heapSize);
299
tgcExtensions->printf(">>> -------------------------------------------------------\n");
300
}
301
302
static void
303
tgcShowHeapStatistics(OMR_VMThread *omrVMThread)
304
{
305
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(omrVMThread);
306
MM_GCExtensionsBase *extensions = MM_GCExtensions::getExtensions(omrVMThread);
307
MM_MemoryPool *memoryPool = extensions->getHeap()->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getMemoryPool();
308
309
tgcExtensions->printf(">>> minimum free entry size: %d\n", memoryPool->getMinimumFreeEntrySize());
310
}
311
312
static void
313
tgcHookSegregatedGlobalGcSweepStartPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
314
{
315
MM_SweepStartEvent* event = (MM_SweepStartEvent *) eventData;
316
tgcShowRegions(event->currentThread, "Before Sweep");
317
}
318
319
static void
320
tgcHookSegregatedGlobalGcSweepEndPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
321
{
322
MM_SweepEndEvent* event = (MM_SweepEndEvent *) eventData;
323
tgcShowRegions(event->currentThread, "After Sweep");
324
tgcShowHeapStatistics(event->currentThread);
325
}
326
327
static void
328
tgcHookSegregatedGlobalGcSynchronousGCStart(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
329
{
330
MM_MetronomeSynchronousGCStartEvent *event = (MM_MetronomeSynchronousGCStartEvent *) eventData;
331
332
if (OUT_OF_MEMORY_TRIGGER == event->reason) {
333
tgcShowRegions(event->currentThread, "Out of Memory");
334
tgcShowHeapStatistics(event->currentThread);
335
}
336
}
337
338
#endif /* defined(J9VM_GC_SEGREGATED_HEAP) */
339
340
341
bool
342
tgcHeapInitialize(J9JavaVM *javaVM)
343
{
344
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
345
J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);
346
J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);
347
348
bool result = true;
349
350
if (extensions->isStandardGC() || extensions->isVLHGC()) {
351
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, tgcHookHeapGlobalPrintStats, OMR_GET_CALLSITE(), NULL);
352
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, tgcHookHeapLocalPrintStats, OMR_GET_CALLSITE(), NULL);
353
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, tgcHookGlobalGcSweepEndPrintStats, OMR_GET_CALLSITE(), NULL);
354
} else if (extensions->isSegregatedHeap()) {
355
#if defined(J9VM_GC_SEGREGATED_HEAP)
356
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, tgcHookSegregatedGlobalGcSweepStartPrintStats, OMR_GET_CALLSITE(), NULL);
357
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, tgcHookSegregatedGlobalGcSweepEndPrintStats, OMR_GET_CALLSITE(), NULL);
358
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, tgcHookSegregatedGlobalGcSynchronousGCStart, OMR_GET_CALLSITE(), NULL);
359
#endif /* defined(J9VM_GC_SEGREGATED_HEAP) */
360
}
361
return result;
362
}
363
364