Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_trace_vlhgc/TgcDynamicCollectionSet.cpp
5986 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2017 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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
22
*******************************************************************************/
23
24
#include "j9.h"
25
#include "j9cfg.h"
26
#include "j9port.h"
27
#include "Tgc.hpp"
28
#include "mmhook.h"
29
30
#include <string.h>
31
32
#include "BaseNonVirtual.hpp"
33
#include "CollectionSetDelegate.hpp"
34
#include "CompactGroupManager.hpp"
35
#include "CompactGroupPersistentStats.hpp"
36
#include "EnvironmentVLHGC.hpp"
37
#include "GCExtensions.hpp"
38
#include "TgcExtensions.hpp"
39
#include "HeapRegionIteratorVLHGC.hpp"
40
#include "HeapRegionDescriptorVLHGC.hpp"
41
42
#define MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH 10
43
44
class MM_TgcDynamicCollectionSetData : public MM_BaseNonVirtual {
45
public:
46
protected:
47
private:
48
struct MM_TgcDynamicCollectionSetHistoryElement {
49
/* Direct measured statistics */
50
UDATA regionCount; /**< Number of regions that appear in the given group */
51
52
/* Historical average of statistics */
53
double avgHis_regionCount; /**< Number of regions that appear in the given group */
54
55
/* Local history average of statistics */
56
double avgLcl_regionCount; /**< Number of regions that appear in the given group */
57
};
58
MM_TgcDynamicCollectionSetHistoryElement *_historyTable[MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH];
59
60
bool _historyPrimed; /**< Flag indicating if the decay analysis history has been primed with initial values or not */
61
62
public:
63
MM_TgcDynamicCollectionSetData();
64
65
static MM_TgcDynamicCollectionSetData *newInstance(J9JavaVM *javaVM);
66
void kill(J9JavaVM *javaVM);
67
68
void dumpDynamicCollectionSetStatistics(MM_EnvironmentVLHGC *env);
69
70
protected:
71
private:
72
bool initialize(J9JavaVM *javaVM);
73
void tearDown(J9JavaVM *javaVM);
74
75
void decayPrintValue(MM_EnvironmentVLHGC *env, UDATA value);
76
void decayPrintDelta(MM_EnvironmentVLHGC *env, UDATA before, UDATA after);
77
};
78
79
MM_TgcDynamicCollectionSetData::MM_TgcDynamicCollectionSetData()
80
: _historyPrimed(false)
81
{
82
_typeId = __FUNCTION__;
83
memset(_historyTable, 0, sizeof(_historyTable));
84
}
85
86
MM_TgcDynamicCollectionSetData *
87
MM_TgcDynamicCollectionSetData::newInstance(J9JavaVM *javaVM)
88
{
89
MM_TgcDynamicCollectionSetData *dcsData = NULL;
90
91
dcsData = (MM_TgcDynamicCollectionSetData *)MM_GCExtensions::getExtensions(javaVM)->getForge()->allocate(sizeof(MM_TgcDynamicCollectionSetData), MM_AllocationCategory::FIXED, J9_GET_CALLSITE());
92
if (NULL != dcsData) {
93
new(dcsData) MM_TgcDynamicCollectionSetData();
94
if (!dcsData->initialize(javaVM)) {
95
dcsData->kill(javaVM);
96
dcsData = NULL;
97
}
98
}
99
100
return dcsData;
101
102
}
103
104
void
105
MM_TgcDynamicCollectionSetData::kill(J9JavaVM *javaVM)
106
{
107
tearDown(javaVM);
108
MM_GCExtensions::getExtensions(javaVM)->getForge()->free(this);
109
}
110
111
bool
112
MM_TgcDynamicCollectionSetData::initialize(J9JavaVM *javaVM)
113
{
114
PORT_ACCESS_FROM_JAVAVM(javaVM);
115
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
116
117
for(UDATA index = 0; index < MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH; index++) {
118
_historyTable[index] = (MM_TgcDynamicCollectionSetHistoryElement *)j9mem_allocate_memory(sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1), OMRMEM_CATEGORY_MM);
119
if(NULL == _historyTable[index]) {
120
goto error_no_memory;
121
}
122
memset(_historyTable[index], 0, sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1));
123
}
124
125
return true;
126
127
error_no_memory:
128
return false;
129
}
130
131
132
void
133
MM_TgcDynamicCollectionSetData::tearDown(J9JavaVM *javaVM)
134
{
135
PORT_ACCESS_FROM_JAVAVM(javaVM);
136
137
for(UDATA index = 0; index < MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH; index++) {
138
if(NULL != _historyTable[index]) {
139
j9mem_free_memory(_historyTable[index]);
140
_historyTable[index] = NULL;
141
}
142
}
143
}
144
145
void
146
MM_TgcDynamicCollectionSetData::decayPrintValue(MM_EnvironmentVLHGC *env, UDATA value)
147
{
148
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));
149
150
char unitTable[] = { 'b', 'k', 'm', 'g', 't' };
151
char *units = &(unitTable[0]);
152
UDATA result = value;
153
UDATA remainder = 0;
154
155
while(result >= 1024) {
156
remainder = result % 1024;
157
result /= 1024;
158
units += 1;
159
}
160
161
if(result >= 100) {
162
tgcExtensions->printf("%4zu%c", result, *units);
163
} else if (result >= 10) {
164
UDATA decimal = (remainder * 10) / 1024;
165
tgcExtensions->printf("%2zu.%1.1zu%c", result, decimal, *units);
166
} else {
167
if(0 == result) {
168
tgcExtensions->printf(" 0");
169
} else {
170
UDATA decimal = (remainder * 100) / 1024;
171
tgcExtensions->printf("%1zu.%2.2zu%c", result, decimal, *units);
172
}
173
}
174
}
175
176
void
177
MM_TgcDynamicCollectionSetData::decayPrintDelta(MM_EnvironmentVLHGC *env, UDATA before, UDATA after)
178
{
179
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));
180
181
if(before >= after) {
182
if(0 == before) {
183
tgcExtensions->printf(" %3zu", 0);
184
} else {
185
UDATA percentage = ((before - after) * 100) / before;
186
tgcExtensions->printf(" %3zu", percentage);
187
}
188
} else {
189
UDATA percentage = ((after - before) * 100) / after;
190
tgcExtensions->printf("(%3zu)", percentage);
191
}
192
}
193
194
void
195
MM_TgcDynamicCollectionSetData::dumpDynamicCollectionSetStatistics(MM_EnvironmentVLHGC *env)
196
{
197
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
198
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
199
200
MM_CollectionSetDelegate::SetSelectionData *setSelectionDataTable = (MM_CollectionSetDelegate::SetSelectionData *)extensions->tarokTgcSetSelectionDataTable;
201
202
/* Right now we'll just gather results and dump them out */
203
204
/* Rotate the table depth such that "0" is the most recent */
205
MM_TgcDynamicCollectionSetHistoryElement *currentHistoryTable = _historyTable[MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH - 1];
206
for(UDATA index = MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH - 1; index > 0; index--) {
207
_historyTable[index] = _historyTable[index - 1];
208
}
209
_historyTable[0] = currentHistoryTable;
210
211
/* Clear the current table of existing data */
212
memset(currentHistoryTable, 0, sizeof(MM_TgcDynamicCollectionSetHistoryElement) * (extensions->tarokRegionMaxAge + 1));
213
214
/* Walk all regions building up statistics */
215
GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::MANAGED);
216
MM_HeapRegionDescriptorVLHGC *region = NULL;
217
while (NULL != (region = regionIterator.nextRegion())) {
218
if (region->containsObjects()) {
219
UDATA ageIndex = region->getLogicalAge();
220
221
Assert_MM_true(region->getLogicalAge() <= extensions->tarokRegionMaxAge);
222
currentHistoryTable[ageIndex].regionCount += 1;
223
}
224
}
225
226
/* Calculate history */
227
double weight = 0.1;
228
if(!_historyPrimed) {
229
_historyPrimed = true;
230
weight = 1.0;
231
}
232
double preserve = 1.0 - weight;
233
234
for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {
235
currentHistoryTable[ageIndex].avgHis_regionCount = _historyTable[1][ageIndex].avgHis_regionCount * preserve;
236
currentHistoryTable[ageIndex].avgHis_regionCount += ((double)currentHistoryTable[ageIndex].regionCount) * weight;
237
238
currentHistoryTable[ageIndex].avgLcl_regionCount = _historyTable[1][ageIndex].avgLcl_regionCount / (double)2.0;
239
currentHistoryTable[ageIndex].avgLcl_regionCount += ((double)currentHistoryTable[ageIndex].regionCount) / (double)2.0;
240
}
241
242
/*
243
* Dump statistics to the TTY.
244
*/
245
tgcExtensions->printf("\n ");
246
for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {
247
tgcExtensions->printf(" %5zu", tableIndex);
248
}
249
250
tgcExtensions->printf("\n ");
251
for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {
252
tgcExtensions->printf("------");
253
}
254
255
/* Region count */
256
tgcExtensions->printf("\nRegCnt ");
257
for(UDATA tableIndex = 0; tableIndex <= extensions->tarokRegionMaxAge; tableIndex++) {
258
tgcExtensions->printf(" %5zu", currentHistoryTable[tableIndex].regionCount);
259
}
260
261
tgcExtensions->printf("\n AvgHis ");
262
for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {
263
tgcExtensions->printf(" %5zu", (UDATA)currentHistoryTable[ageIndex].avgHis_regionCount);
264
}
265
266
tgcExtensions->printf("\n AvgH%2zu ", MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH);
267
for(UDATA ageIndex = 0; ageIndex <= extensions->tarokRegionMaxAge; ageIndex++) {
268
tgcExtensions->printf(" %5zu", (UDATA)currentHistoryTable[ageIndex].avgLcl_regionCount);
269
}
270
271
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
272
tgcExtensions->printf("\nROR ");
273
MM_CompactGroupPersistentStats *persistentStats = extensions->compactGroupPersistentStats;
274
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
275
double rateOfReturn = 1.0 - persistentStats[compactGroupIndex]._historicalSurvivalRate;
276
tgcExtensions->printf(" %5zu", (UDATA)(rateOfReturn * (double)1000.0));
277
}
278
279
tgcExtensions->printf("\n RgCtB ");
280
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
281
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountBefore);
282
}
283
tgcExtensions->printf("\n RgLfB ");
284
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
285
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafBefore);
286
}
287
tgcExtensions->printf("\n RgCtA ");
288
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
289
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountAfter);
290
}
291
tgcExtensions->printf("\n RgLfA ");
292
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
293
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafAfter);
294
}
295
296
tgcExtensions->printf("\n RgOv ");
297
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
298
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountOverflow);
299
}
300
tgcExtensions->printf("\n RgLfOv");
301
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
302
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._regionCountArrayletLeafOverflow);
303
}
304
305
tgcExtensions->printf("\n RcRgB ");
306
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
307
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountBefore);
308
}
309
tgcExtensions->printf("\n RcLfB ");
310
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
311
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountArrayletLeafBefore);
312
}
313
tgcExtensions->printf("\n RcRgA ");
314
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
315
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountAfter);
316
}
317
tgcExtensions->printf("\n RcLfA ");
318
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
319
tgcExtensions->printf(" %5zu", setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableRegionCountArrayletLeafAfter);
320
}
321
322
tgcExtensions->printf("\n RcBcB ");
323
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
324
tgcExtensions->printf(" ");
325
decayPrintValue(env, setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableBytesConsumedBefore);
326
}
327
tgcExtensions->printf("\n RcBcA ");
328
for(UDATA compactGroupIndex = 0; compactGroupIndex < compactGroupCount; compactGroupIndex++) {
329
tgcExtensions->printf(" ");
330
decayPrintValue(env, setSelectionDataTable[compactGroupIndex]._reclaimStats._reclaimableBytesConsumedAfter);
331
}
332
333
tgcExtensions->printf("\n");
334
}
335
336
/**
337
* Report dynamic collection set statistics for PGC.
338
*/
339
static void
340
tgcHookReportDynamicCollectionSetStatistics(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
341
{
342
MM_VlhgcGarbageCollectCompletedEvent* event = (MM_VlhgcGarbageCollectCompletedEvent*)eventData;
343
MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(event->currentThread);
344
345
if(MM_GCExtensions::getExtensions(env)->tarokEnableDynamicCollectionSetSelection) {
346
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));
347
MM_TgcDynamicCollectionSetData *dcsData = (MM_TgcDynamicCollectionSetData *)tgcExtensions->_dynamicCollectionSetData;
348
dcsData->dumpDynamicCollectionSetStatistics(env);
349
}
350
}
351
352
/**
353
* Dump a legend of terms to the tty.
354
*/
355
void
356
dumpLegend(J9JavaVM *javaVM)
357
{
358
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(javaVM);
359
360
tgcExtensions->printf("\nTGC Dynamic Collection Set Glossary");
361
tgcExtensions->printf("\n-----------------------------------");
362
363
/* Region count */
364
tgcExtensions->printf("\nRegCnt - Number of regions found in the age group");
365
tgcExtensions->printf("\n AvgHis - Historical average number of regions found in the age group");
366
tgcExtensions->printf("\n AvgHxx - Half-life average number of regions found in the age group for the last %zu iterations", (UDATA)MM_TGC_DYNAMIC_COLLECTION_SET_HISTORY_TABLE_DEPTH);
367
368
tgcExtensions->printf("\nROR - Rate of return when collecting (trace) the region set (amount of currently consumed data that is rendered reclaimable)");
369
tgcExtensions->printf("\n RgCtB - Region count before collection");
370
tgcExtensions->printf("\n RgLfB - Leaf region count before collection");
371
tgcExtensions->printf("\n RgCtA - Region count after collection");
372
tgcExtensions->printf("\n RgLfA - Leaf region count after collection");
373
374
tgcExtensions->printf("\n RgOv - Regions in an overflow state (uncollectable through normal means)");
375
tgcExtensions->printf("\n RgLfOv - Leaf regions in an overflow state as a consequence of their parents being overflowed");
376
377
tgcExtensions->printf("\n RcRgB - Reclaimable region count before collection (those marked as part of the collection set)");
378
tgcExtensions->printf("\n RcLfB - Reclaimable leaf region count before collection");
379
tgcExtensions->printf("\n RcRgA - Reclaimable region count after collection");
380
tgcExtensions->printf("\n RcLfA - Reclaimable leaf region count after collection");
381
382
tgcExtensions->printf("\n RcBcB - Reclaimable region bytes consumed before collection");
383
tgcExtensions->printf("\n RcBcA - Reclaimable region bytes consumed after collection");
384
385
tgcExtensions->printf("\n");
386
}
387
388
/**
389
* Initialize dynamic collection set tgc tracing.
390
* Attaches hooks to the appropriate functions handling events used by dynamic collection set tgc tracing.
391
*/
392
bool
393
tgcDynamicCollectionSetInitialize(J9JavaVM *javaVM)
394
{
395
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
396
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
397
bool result = true;
398
399
tgcExtensions->_dynamicCollectionSetData = MM_TgcDynamicCollectionSetData::newInstance(javaVM);
400
if(NULL != tgcExtensions->_dynamicCollectionSetData) {
401
J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);
402
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_VLHGC_GARBAGE_COLLECT_COMPLETED, tgcHookReportDynamicCollectionSetStatistics, OMR_GET_CALLSITE(), NULL);
403
dumpLegend(javaVM);
404
} else {
405
result = false;
406
}
407
return result;
408
}
409
410
/**
411
* Tear down dynamic collection set tgc tracing.
412
* Cleans up any support structures related to the specific tgc facility.
413
*/
414
void
415
tgcDynamicCollectionSetTearDown(J9JavaVM *javaVM)
416
{
417
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
418
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
419
420
if(NULL != tgcExtensions->_dynamicCollectionSetData) {
421
((MM_TgcDynamicCollectionSetData *)tgcExtensions->_dynamicCollectionSetData)->kill(javaVM);
422
tgcExtensions->_dynamicCollectionSetData = NULL;
423
}
424
}
425
426