Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_trace_standard/TgcLargeAllocation.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 "j9port.h"
26
#include "modronopt.h"
27
#include "mmhook.h"
28
29
#include "ConcurrentGCStats.hpp"
30
#include "EnvironmentBase.hpp"
31
#include "GCExtensions.hpp"
32
#include "Heap.hpp"
33
#include "HeapMemoryPoolIterator.hpp"
34
#include "HeapMemorySubSpaceIterator.hpp"
35
#include "LargeObjectAllocateStats.hpp"
36
#include "MemoryPool.hpp"
37
#include "MemorySpace.hpp"
38
#include "MemorySubSpace.hpp"
39
#include "ScanClassesMode.hpp"
40
#include "TgcExtensions.hpp"
41
#include "TgcLargeAllocation.hpp"
42
43
static void
44
tgcFreeMemoryPrintStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)
45
{
46
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
47
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
48
49
MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();
50
51
if (NULL != stats) {
52
53
tgcExtensions->printf(" -------------------------------------\n");
54
tgcExtensions->printf(" %llx (%s) pool: \n", memoryPool, memoryPool->getPoolName());
55
tgcExtensions->printf(" Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");
56
57
UDATA totalCount = 0;
58
UDATA approxTotalFreeMemory = 0;
59
for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {
60
UDATA count = stats->getFreeEntrySizeClassStats()->getCount(sizeClassIndex);
61
UDATA frequentAllocCount = stats->getFreeEntrySizeClassStats()->getFrequentAllocCount(sizeClassIndex);
62
count += frequentAllocCount;
63
if (0 != count) {
64
totalCount += count;
65
UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);
66
67
MM_FreeEntrySizeClassStats::FrequentAllocation *curr = stats->getFreeEntrySizeClassStats()->getFrequentAllocationHead(sizeClassIndex);
68
UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();
69
while (NULL != curr) {
70
if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {
71
tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);
72
} else {
73
tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);
74
}
75
approxFreeMemory += (curr->_size * curr->_count);
76
curr = curr->_nextInSizeClass;
77
}
78
approxTotalFreeMemory += approxFreeMemory;
79
80
Assert_MM_true(frequentAllocCount <= count);
81
82
tgcExtensions->printf(" %4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",
83
sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,
84
approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),
85
approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());
86
}
87
}
88
tgcExtensions->printf(" Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",
89
totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);
90
Assert_MM_true(totalCount == memoryPool->getActualFreeEntryCount());
91
}
92
}
93
94
static void
95
tgcTlhAllocPrintStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)
96
{
97
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
98
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
99
100
MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();
101
102
if (NULL != stats) {
103
104
tgcExtensions->printf(" -------------------------------------\n");
105
tgcExtensions->printf(" %llx (%s) pool - TLH alloc: \n", memoryPool, memoryPool->getPoolName());
106
tgcExtensions->printf(" Index SizeClass tlhCount tlhKBytes\n");
107
108
for (IDATA sizeClassIndex = (IDATA)stats->getMaxTLHSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {
109
UDATA countTlhAlloc = stats->getTlhAllocSizeClassCount(sizeClassIndex);
110
if (0 != countTlhAlloc) {
111
UDATA approxTlhAllocMemory = countTlhAlloc * stats->getSizeClassSizes(sizeClassIndex);
112
tgcExtensions->printf(" %4zu %11zu %8zu %9zuK\n",
113
sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), countTlhAlloc, approxTlhAllocMemory >> 10);
114
}
115
}
116
}
117
118
}
119
120
static void
121
tgcFreeMemoryPrintStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace, bool globalGC)
122
{
123
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
124
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
125
126
MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();
127
128
if (NULL != stats) {
129
MM_MemoryPool *memoryPool = memorySubSpace->getMemoryPool();
130
131
tgcExtensions->printf("-------------------------------------\n");
132
tgcExtensions->printf("Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");
133
134
UDATA totalCount = 0;
135
UDATA approxTotalFreeMemory = 0;
136
for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {
137
UDATA count = stats->getFreeEntrySizeClassStats()->getCount(sizeClassIndex);
138
UDATA frequentAllocCount = stats->getFreeEntrySizeClassStats()->getFrequentAllocCount(sizeClassIndex);
139
count += frequentAllocCount;
140
if (0 != count) {
141
totalCount += count;
142
UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);
143
144
Assert_MM_true(frequentAllocCount <= count);
145
146
MM_FreeEntrySizeClassStats::FrequentAllocation *curr = stats->getFreeEntrySizeClassStats()->getFrequentAllocationHead(sizeClassIndex);
147
UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();
148
while (NULL != curr) {
149
if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {
150
tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);
151
} else {
152
tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);
153
}
154
approxFreeMemory += (curr->_size * curr->_count);
155
curr = curr->_nextInSizeClass;
156
}
157
approxTotalFreeMemory += approxFreeMemory;
158
159
tgcExtensions->printf("%4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",
160
sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,
161
approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),
162
approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());
163
}
164
}
165
tgcExtensions->printf("Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",
166
totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);
167
Assert_MM_true(totalCount == memoryPool->getActualFreeEntryCount());
168
169
if ((globalGC && (GLOBALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & GLOBALGC_ESTIMATE_FRAGMENTATION))) ||
170
(!globalGC && (LOCALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & LOCALGC_ESTIMATE_FRAGMENTATION)))) {
171
tgcExtensions->printf("------------- Fragmented Remainder ------------------------\n");
172
tgcExtensions->printf("Index SizeClass Count FreqAlloc MBytes ( Pct) Cumulative ( Pct)\n");
173
174
totalCount = 0;
175
approxTotalFreeMemory = 0;
176
for (IDATA sizeClassIndex = (IDATA)stats->getMaxSizeClasses() - 1; sizeClassIndex >=0 ; sizeClassIndex--) {
177
UDATA count = extensions->freeEntrySizeClassStatsSimulated.getCount(sizeClassIndex);
178
UDATA frequentAllocCount = extensions->freeEntrySizeClassStatsSimulated.getFrequentAllocCount(sizeClassIndex);
179
count += frequentAllocCount;
180
if (0 != count) {
181
totalCount += count;
182
UDATA approxFreeMemory = (count - frequentAllocCount) * stats->getSizeClassSizes(sizeClassIndex);
183
184
MM_FreeEntrySizeClassStats::FrequentAllocation *curr = extensions->freeEntrySizeClassStatsSimulated.getFrequentAllocationHead(sizeClassIndex);
185
UDATA veryLargeEntrySizeClass = stats->getFreeEntrySizeClassStats()->getVeryLargeEntrySizeClass();
186
while (NULL != curr) {
187
if (sizeClassIndex >= (IDATA)veryLargeEntrySizeClass) {
188
tgcExtensions->printf(" VeryLarge size %8zu count %8zu\n", curr->_size, curr->_count);
189
} else {
190
tgcExtensions->printf(" Frequent size %8zu count %8zu\n", curr->_size, curr->_count);
191
}
192
approxFreeMemory += (curr->_size * curr->_count);
193
Assert_MM_true(stats->getSizeClassIndex(curr->_size) == (UDATA)sizeClassIndex);
194
curr = curr->_nextInSizeClass;
195
}
196
approxTotalFreeMemory += approxFreeMemory;
197
198
tgcExtensions->printf("%4zu %11zu %8zu %9zu %9zuM (%5.2f%%) %9zuM (%5.2f%%)\n",
199
sizeClassIndex, stats->getSizeClassSizes(sizeClassIndex), count, frequentAllocCount,
200
approxFreeMemory >> 20, 100 * (float)approxFreeMemory/(float)memoryPool->getActualFreeMemorySize(),
201
approxTotalFreeMemory >> 20, 100 * (float)approxTotalFreeMemory/(float)memoryPool->getActualFreeMemorySize());
202
203
Assert_MM_true(frequentAllocCount <= count);
204
}
205
}
206
tgcExtensions->printf("Total Count: %zu (%zu). Approx total free memory: %zuMB (%zuMB)\n",
207
totalCount, memoryPool->getActualFreeEntryCount(), approxTotalFreeMemory >> 20, memoryPool->getActualFreeMemorySize() >> 20);
208
}
209
}
210
}
211
212
static void
213
tgcLargeAllocationPrintCurrentStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)
214
{
215
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
216
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
217
218
MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();
219
220
if (NULL != stats) {
221
tgcExtensions->printf(" --------------------------------------\n");
222
tgcExtensions->printf(" %llx (%s) pool - CURRENT:\n", memoryPool, memoryPool->getPoolName());
223
tgcExtensions->printf(" Rank | Size KBytes Count | SizeClass KBytes Count\n");
224
225
for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizes()) && i < stats->getMaxAllocateSizes(); i++) {
226
UDATA size = 0;
227
UDATA sizeCount = 0;
228
size = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizes(), i + 1);
229
if (0 != size) {
230
sizeCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizes(), i + 1) / size;
231
}
232
233
UDATA sizeClass = 0;
234
UDATA sizeClassCount = 0;
235
if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizeClasses())) {
236
sizeClass = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClasses(), i + 1);
237
if (0 != sizeClass) {
238
sizeClassCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClasses(), i + 1) / sizeClass;
239
}
240
}
241
242
tgcExtensions->printf(" %4zu | %9zu %10zuK %6zu | %9zu %10zuK %6zu\n",
243
i, size, sizeCount * size >> 10, sizeCount, sizeClass, sizeClass * sizeClassCount >> 10, sizeClassCount);
244
}
245
}
246
}
247
248
static void
249
tgcLargeAllocationPrintAverageStatsForMemoryPool(OMR_VMThread* omrVMThread, MM_MemoryPool *memoryPool)
250
{
251
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
252
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
253
254
MM_LargeObjectAllocateStats *stats = memoryPool->getLargeObjectAllocateStats();
255
256
if (NULL != stats) {
257
tgcExtensions->printf(" -------------------------------------\n");
258
tgcExtensions->printf(" %llx (%s) pool - AVERAGE:\n", memoryPool, memoryPool->getPoolName());
259
tgcExtensions->printf(" Rank | Size BytesPct | SizeClass BytesPct\n");
260
261
for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent()) && i < stats->getMaxAllocateSizes(); i++) {
262
263
UDATA sizeForAveragePercent = 0;
264
float averagePercent = 0;
265
if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent())) {
266
sizeForAveragePercent = (UDATA)spaceSavingGetKthMostFreq(stats->getSpaceSavingSizesAveragePercent(), i + 1);
267
averagePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizesAveragePercent(), i + 1));
268
}
269
270
UDATA sizeClassForAveragePercent = 0;
271
float sizeClassAveragePercent = 0;
272
if (i < spaceSavingGetCurSize(stats->getSpaceSavingSizeClassesAveragePercent())) {
273
sizeClassForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1);
274
sizeClassAveragePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1));
275
}
276
277
tgcExtensions->printf(" %4zu | %9zu %7.4f%% | %9zu %7.4f%%\n",
278
i, sizeForAveragePercent, averagePercent, sizeClassForAveragePercent, sizeClassAveragePercent);
279
}
280
281
282
}
283
}
284
285
static void
286
tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace)
287
{
288
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
289
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
290
291
/* we fetch directly the stats from the SubSpace. It will know if it needs to merge stats from child SubSpaces/Pools, or fetch directly from child Pool */
292
MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();
293
294
if (NULL != stats) {
295
296
tgcExtensions->printf("---------------- CURRENT ----------------\n");
297
tgcExtensions->printf("Rank | Size KBytes Count | SizeClass KBytes Count\n");
298
299
for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizes()) && i < stats->getMaxAllocateSizes(); i++){
300
UDATA size = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizes(), i + 1);
301
UDATA sizeCount = 0;
302
if (0 != size) {
303
sizeCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizes() ,i + 1) / size;
304
}
305
UDATA sizeClass = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClasses(), i + 1);
306
UDATA sizeClassCount = 0;
307
if (0 != sizeClass) {
308
sizeClassCount = spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClasses(), i + 1) / sizeClass;
309
}
310
311
tgcExtensions->printf("%4zu | %9zu %10zuK %6zu | %9zu %10zuK %6zu\n",
312
i, size, sizeCount * size >> 10, sizeCount, sizeClass, sizeClass * sizeClassCount >> 10, sizeClassCount);
313
}
314
}
315
}
316
317
static void
318
tgcLargeAllocationPrintAverageStatsForMemorySubSpace(OMR_VMThread* omrVMThread, MM_MemorySubSpace *memorySubSpace)
319
{
320
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
321
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
322
323
/* we fetch directly the stats from the SubSpace. It will know if it needs to merge stats from child SubSpaces/Pools, or fetch directly from child Pool */
324
MM_LargeObjectAllocateStats *stats = memorySubSpace->getLargeObjectAllocateStats();
325
326
if (NULL != stats) {
327
tgcExtensions->printf("---------------- AVERAGE ----------------\n");
328
tgcExtensions->printf("Rank | Size BytesPct | SizeClass BytesPct\n");
329
330
for(U_16 i = 0; i < spaceSavingGetCurSize(stats->getSpaceSavingSizesAveragePercent()) && i < stats->getMaxAllocateSizes(); i++){
331
UDATA sizeForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizesAveragePercent(), i + 1);
332
float averagePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizesAveragePercent(), i + 1));
333
334
UDATA sizeClassForAveragePercent = (UDATA) spaceSavingGetKthMostFreq(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1);
335
float sizeClassAveragePercent = stats->convertPercentUDATAToFloat(spaceSavingGetKthMostFreqCount(stats->getSpaceSavingSizeClassesAveragePercent(), i + 1));
336
337
tgcExtensions->printf("%4zu | %9zu %7.4f%% | %9zu %7.4f%%\n",
338
i, sizeForAveragePercent, averagePercent, sizeClassForAveragePercent, sizeClassAveragePercent);
339
}
340
}
341
}
342
343
static void
344
tgcLargeAllocationPrintStatsForAllocateMemory(OMR_VMThread* omrVMThread)
345
{
346
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
347
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
348
349
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
350
MM_MemorySubSpace *defaultMemorySubspace = defaultMemorySpace->getDefaultMemorySubSpace();
351
352
if (defaultMemorySubspace->isPartOfSemiSpace()) {
353
tgcExtensions->printf("======== Large Allocation Statistics ========\n");
354
355
/* We are in generational configuration. defaultMemorySubspace points to one of two allocate Subspaces, but we want both. Thus we access the parent (SemiSpace subspace) */
356
/* SemiSpace stats include only Mutator stats (no Collector stats during flipping) */
357
MM_MemorySubSpace *topLevelMemorySubSpaceNew = defaultMemorySubspace->getTopLevelMemorySubSpace(MEMORY_TYPE_NEW);
358
tgcExtensions->printf("Allocate subspace: %llx (%s)\n", topLevelMemorySubSpaceNew, topLevelMemorySubSpaceNew->getName());
359
tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(omrVMThread, topLevelMemorySubSpaceNew);
360
tgcExtensions->printf("=============================================\n");
361
}
362
}
363
364
static void
365
tgcLargeAllocationPrintCurrentStatsForTenureMemory(OMR_VMThread* omrVMThread)
366
{
367
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
368
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
369
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);
370
371
tgcExtensions->printf("==== Large Allocation Current Statistics ====\n");
372
373
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
374
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
375
376
/* Note that tenure stats:
377
* for Generational: will include stats both Collector and Mutator allocates
378
* for Flat: will include stats only Mutator allocates
379
*/
380
tgcExtensions->printf("Tenure subspace: %llx (%s) - CURRENT \n", tenureMemorySubspace, tenureMemorySubspace->getName());
381
tgcLargeAllocationPrintCurrentStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace);
382
383
MM_MemoryPool *memoryPool = NULL;
384
MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);
385
386
while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {
387
tgcTlhAllocPrintStatsForMemoryPool(omrVMThread, memoryPool);
388
tgcLargeAllocationPrintCurrentStatsForMemoryPool(omrVMThread, memoryPool);
389
}
390
391
tgcExtensions->printf("=============================================\n");
392
}
393
394
static void
395
tgcLargeAllocationPrintAverageStatsForTenureMemory(OMR_VMThread* omrVMThread, UDATA eventNum)
396
{
397
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
398
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
399
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);
400
401
tgcExtensions->printf("==== Large Allocation Average Statistics ====\n");
402
403
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
404
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
405
406
/* Note that tenure stats:
407
* for Generational: will include stats both Collector and Mutator allocates
408
* for Flat: will include stats only Mutator allocates
409
*/
410
MM_MemoryPool *memoryPool = NULL;
411
MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);
412
413
while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {
414
415
tgcLargeAllocationPrintAverageStatsForMemoryPool(omrVMThread, memoryPool);
416
}
417
418
tgcExtensions->printf("Tenure subspace: %llx (%s) - AVERAGE\n", tenureMemorySubspace, tenureMemorySubspace->getName());
419
tgcLargeAllocationPrintAverageStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace);
420
421
tgcExtensions->printf("=============================================\n");
422
}
423
424
static void
425
tgcFreeMemoryPrintStats(OMR_VMThread* omrVMThread, bool globalGC)
426
{
427
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
428
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
429
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread);
430
431
tgcExtensions->printf("=========== Free Memory Statistics ==========\n");
432
tgcExtensions->printf("=========== Size Class Distribution =========\n");
433
434
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
435
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
436
437
MM_MemoryPool *memoryPool = NULL;
438
MM_HeapMemoryPoolIterator poolIterator(env, extensions->heap, tenureMemorySubspace);
439
440
while (NULL != (memoryPool = poolIterator.nextPoolInSubSpace())) {
441
tgcFreeMemoryPrintStatsForMemoryPool(omrVMThread, memoryPool);
442
}
443
444
tgcExtensions->printf("Tenure subspace: %llx (%s)\n", tenureMemorySubspace, tenureMemorySubspace->getName());
445
tgcFreeMemoryPrintStatsForMemorySubSpace(omrVMThread, tenureMemorySubspace, globalGC);
446
447
tgcExtensions->printf("=============================================\n");
448
}
449
450
static void
451
tgcEstimateFragmentationPrintStats(OMR_VMThread* omrVMThread)
452
{
453
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
454
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
455
456
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
457
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
458
MM_LargeObjectAllocateStats* stats = tenureMemorySubspace->getLargeObjectAllocateStats();
459
460
OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);
461
U_64 time = omrtime_hires_delta(0, stats->getTimeEstimateFragmentation(), J9PORT_TIME_DELTA_IN_MICROSECONDS);
462
U_64 cpuTime = stats->getCPUTimeEstimateFragmentation();
463
if (cpuTime > time) {
464
cpuTime = 0;
465
}
466
char timestamp[32];
467
omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());
468
tgcExtensions->printf("<tgcLargeAllocation op=\"estimateFragmentation\" timems=\"%llu.%03.3llu\" cputimes=\"%llu.%03.3llu\" remainingFreeMemory=\"%zu\" initialFreeMemory=\"%zu\" timestamp=\"%s\" />\n",
469
time/1000, time%1000, cpuTime/1000, cpuTime%1000, stats->getRemainingFreeMemoryAfterEstimate(), stats->getFreeMemoryBeforeEstimate(), timestamp);
470
471
}
472
473
/**
474
* print time for mergeLargeAllocateStats, mergeTLH, mergeFreeEntry and averageLargeAllocateStats
475
*/
476
static void
477
tgcMergeAveragePrintStats(OMR_VMThread* omrVMThread)
478
{
479
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVMThread);
480
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
481
MM_MemorySpace *defaultMemorySpace = extensions->heap->getDefaultMemorySpace();
482
MM_MemorySubSpace *tenureMemorySubspace = defaultMemorySpace->getTenureMemorySubSpace();
483
MM_LargeObjectAllocateStats* stats = tenureMemorySubspace->getLargeObjectAllocateStats();
484
485
OMRPORT_ACCESS_FROM_OMRVMTHREAD(omrVMThread);
486
U_64 time = omrtime_hires_delta(0, stats->getTimeMergeAverage(), J9PORT_TIME_DELTA_IN_MICROSECONDS);
487
char timestamp[32];
488
omrstr_ftime(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", omrtime_current_time_millis());
489
tgcExtensions->printf("<tgcLargeAllocation op=\"mergeAndAverage\" timems=\"%llu.%03.3llu\" timestamp=\"%s\" />\n",
490
time/1000, time%1000, timestamp);
491
492
}
493
494
static void
495
tgcVerifyBackoutInScavenger(J9VMThread* vmThread)
496
{
497
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread);
498
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
499
500
MM_ScavengerStats *scavengerStats = (MM_ScavengerStats *)&extensions->scavengerStats;
501
if(scavengerStats->_backout) {
502
tgcExtensions->printf("<tgcLargeAllocation op=\"gc\" type=\"scavenge\" details=\"aborted collection due to insufficient free space\" />\n");
503
}
504
}
505
506
static void
507
tgcHookLargeAllocationGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
508
{
509
MM_GlobalGCEndEvent* event = (MM_GlobalGCEndEvent*)eventData;
510
tgcLargeAllocationPrintCurrentStatsForTenureMemory(event->currentThread);
511
tgcLargeAllocationPrintAverageStatsForTenureMemory(event->currentThread, eventNum);
512
tgcLargeAllocationPrintStatsForAllocateMemory(event->currentThread);
513
}
514
515
static void
516
tgcHookLargeAllocationLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
517
{
518
if (J9HOOK_MM_OMR_LOCAL_GC_START == eventNum) {
519
MM_LocalGCStartEvent* event = (MM_LocalGCStartEvent*)eventData;
520
tgcLargeAllocationPrintStatsForAllocateMemory(event->currentThread);
521
} else if (J9HOOK_MM_OMR_LOCAL_GC_END == eventNum) {
522
MM_LocalGCEndEvent* event = (MM_LocalGCEndEvent*)eventData;
523
tgcLargeAllocationPrintCurrentStatsForTenureMemory(event->currentThread);
524
tgcLargeAllocationPrintAverageStatsForTenureMemory(event->currentThread, eventNum);
525
} else {
526
Assert_MM_unreachable();
527
}
528
529
}
530
531
static void
532
tgcHookFreeMemoryGlobalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
533
{
534
MM_GlobalGCEndEvent* event = (MM_GlobalGCEndEvent*)eventData;
535
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(event->currentThread);
536
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
537
538
if (tgcExtensions->_largeAllocationVerboseRequested) {
539
tgcFreeMemoryPrintStats(event->currentThread, true);
540
}
541
tgcMergeAveragePrintStats(event->currentThread);
542
if (GLOBALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & GLOBALGC_ESTIMATE_FRAGMENTATION)) {
543
tgcEstimateFragmentationPrintStats(event->currentThread);
544
}
545
}
546
547
static void
548
tgcHookFreeMemoryLocalPrintStats(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
549
{
550
MM_LocalGCEndEvent* event = (MM_LocalGCEndEvent*)eventData;
551
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(event->currentThread);
552
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
553
554
if (tgcExtensions->_largeAllocationVerboseRequested) {
555
tgcFreeMemoryPrintStats(event->currentThread, false);
556
}
557
558
tgcVerifyBackoutInScavenger((J9VMThread *) event->currentThread->_language_vmthread);
559
tgcMergeAveragePrintStats(event->currentThread);
560
if (LOCALGC_ESTIMATE_FRAGMENTATION == (extensions->estimateFragmentation & LOCALGC_ESTIMATE_FRAGMENTATION)) {
561
tgcEstimateFragmentationPrintStats(event->currentThread);
562
}
563
}
564
565
static void
566
tgcVerifyHaltedInConcurrentGC(J9VMThread* vmThread, const char* state, const char* status)
567
{
568
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread);
569
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
570
tgcExtensions->printf("<tgcLargeAllocation op=\"gc\" type=\"concurrent\" details=\"concurrent-halted\" state=\"%s\" status=\"%s\" />\n", state, status);
571
}
572
573
static void
574
tgcHookVerifyHaltedInConcurrentGC(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
575
{
576
MM_ConcurrentHaltedEvent* event = (MM_ConcurrentHaltedEvent*)eventData;
577
#define CONCURRENT_STATUS_BUFFER_LENGTH 32
578
char statusBuffer[CONCURRENT_STATUS_BUFFER_LENGTH];
579
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(event->currentThread);
580
const char* statusString = MM_ConcurrentGCStats::getConcurrentStatusString(env, event->executionMode, statusBuffer, CONCURRENT_STATUS_BUFFER_LENGTH);
581
#undef CONCURRENT_STATUS_BUFFER_LENGTH
582
583
const char* stateString = "Complete";
584
if (0 == event->isTracingExhausted) {
585
stateString = "Tracing incomplete";
586
}
587
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
588
switch (event->scanClassesMode) {
589
case MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED:
590
case MM_ScanClassesMode::SCAN_CLASSES_CURRENTLY_ACTIVE:
591
stateString = "Class scanning incomplete";
592
break;
593
case MM_ScanClassesMode::SCAN_CLASSES_COMPLETE:
594
case MM_ScanClassesMode::SCAN_CLASSES_DISABLED:
595
break;
596
default:
597
stateString = "Class scanning bad state";
598
break;
599
}
600
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
601
if (0 == event->isCardCleaningComplete) {
602
stateString = "Card cleaning incomplete";
603
}
604
605
tgcVerifyHaltedInConcurrentGC(static_cast<J9VMThread*>(event->currentThread->_language_vmthread), stateString, statusString);
606
}
607
608
bool
609
tgcLargeAllocationInitialize(J9JavaVM *javaVM)
610
{
611
bool result = true;
612
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
613
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
614
615
/*TODO: remove condition check for concurrentSweep, currently tgc:largeAllocation can not be enabled in concurrentSweep case */
616
if (extensions->processLargeAllocateStats && extensions->isStandardGC()) {
617
if (!extensions->isConcurrentSweepEnabled()) {
618
J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);
619
if (tgcExtensions->_largeAllocationVerboseRequested) {
620
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, tgcHookLargeAllocationGlobalPrintStats, OMR_GET_CALLSITE(), NULL);
621
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, tgcHookLargeAllocationLocalPrintStats, OMR_GET_CALLSITE(), NULL);
622
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, tgcHookLargeAllocationLocalPrintStats, OMR_GET_CALLSITE(), NULL);
623
}
624
625
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, tgcHookFreeMemoryGlobalPrintStats, OMR_GET_CALLSITE(), NULL);
626
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, tgcHookFreeMemoryLocalPrintStats, OMR_GET_CALLSITE(), NULL);
627
628
J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);
629
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_CONCURRENT_HALTED, tgcHookVerifyHaltedInConcurrentGC, OMR_GET_CALLSITE(), NULL);
630
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_COMPACT_START, tgcHookFreeMemoryGlobalPrintStats, OMR_GET_CALLSITE(), NULL);
631
}
632
}
633
return result;
634
}
635
636