Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_vlhgc/CompactGroupPersistentStats.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 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 <string.h>
24
#include <math.h>
25
26
27
#include "CompactGroupPersistentStats.hpp"
28
29
#include "AllocationContextTarok.hpp"
30
#include "CompactGroupManager.hpp"
31
#include "EnvironmentVLHGC.hpp"
32
#include "GCExtensions.hpp"
33
#include "GlobalAllocationManagerTarok.hpp"
34
#include "HeapRegionIteratorVLHGC.hpp"
35
#include "HeapRegionManager.hpp"
36
#include "IncrementalGenerationalGC.hpp"
37
#include "Math.hpp"
38
39
MM_CompactGroupPersistentStats *
40
MM_CompactGroupPersistentStats::allocateCompactGroupPersistentStats(MM_EnvironmentVLHGC *env)
41
{
42
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
43
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
44
UDATA persistentStatsAllocationSize = sizeof(MM_CompactGroupPersistentStats) * compactGroupCount;
45
46
MM_CompactGroupPersistentStats * result = (MM_CompactGroupPersistentStats *)extensions->getForge()->allocate(persistentStatsAllocationSize, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());
47
if (NULL != result) {
48
memset(result, 0x0, persistentStatsAllocationSize);
49
for (UDATA i = 0; i < compactGroupCount; i++) {
50
result[i]._historicalSurvivalRate = 1.0;
51
result[i]._weightedSurvivalRate = 1.0;
52
result[i]._projectedInstantaneousSurvivalRate = 1.0;
53
result[i]._projectedInstantaneousSurvivalRatePerAgeUnit = 1.0;
54
result[i]._projectedInstantaneousSurvivalRateThisPGCPerAgeUnit = 1.0;
55
result[i]._projectedLiveBytes = 0;
56
result[i]._liveBytesAbsoluteDeviation = 0;
57
result[i]._regionCount = 0;
58
result[i]._statsHaveBeenUpdatedThisCycle = false;
59
/* this is not really stats, but a constant; calculate only if unit is set */
60
if (0 != extensions->tarokAllocationAgeUnit) {
61
UDATA ageGroup = MM_CompactGroupManager::getRegionAgeFromGroup(env, i);
62
if (ageGroup != extensions->tarokRegionMaxAge) {
63
result[i]._maxAllocationAge = MM_CompactGroupManager::calculateMaximumAllocationAge(env, ageGroup + 1);
64
} else {
65
result[i]._maxAllocationAge = UDATA_MAX;
66
}
67
}
68
}
69
}
70
return result;
71
}
72
73
void
74
MM_CompactGroupPersistentStats::killCompactGroupPersistentStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
75
{
76
MM_GCExtensions::getExtensions(env)->getForge()->free(persistentStats);
77
}
78
79
80
void
81
MM_CompactGroupPersistentStats::deriveWeightedSurvivalRates(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
82
{
83
/* this weight is completely arbitrary */
84
const double olderWeight = 0.7;
85
const double thisWeight = 1.0 - olderWeight;
86
Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_Entry(env->getLanguageVMThread(), olderWeight);
87
88
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
89
MM_GlobalAllocationManagerTarok *allocationManager = (MM_GlobalAllocationManagerTarok*)extensions->globalAllocationManager;
90
91
UDATA regionMaxAge = extensions->tarokRegionMaxAge;
92
UDATA managedAllocationContextCount = allocationManager->getManagedAllocationContextCount();
93
for (UDATA contextIndex = 0; contextIndex < managedAllocationContextCount; contextIndex++) {
94
MM_AllocationContextTarok *context = allocationManager->getAllocationContextByIndex(contextIndex);
95
double olderSurvivalRate = 1.0;
96
97
/* process the compact groups from oldest to youngest (note that the for loop relies on integer-underflow) */
98
for (UDATA age = regionMaxAge; age <= regionMaxAge; age--) {
99
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumberForAge(env, age, context);
100
101
double thisSurvivalRate = persistentStats[compactGroup]._historicalSurvivalRate;
102
double weightedSurvivalRate = (olderWeight * olderSurvivalRate) + (thisWeight * thisSurvivalRate);
103
/* the historical rate may decrease the apparent survival rate but isn't permitted to increase it */
104
weightedSurvivalRate = OMR_MIN(weightedSurvivalRate, thisSurvivalRate);
105
106
Assert_MM_true(0.0 <= weightedSurvivalRate);
107
Assert_MM_true(1.0 >= weightedSurvivalRate);
108
109
persistentStats[compactGroup]._weightedSurvivalRate = weightedSurvivalRate;
110
111
Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_group(env->getLanguageVMThread(), contextIndex, age, thisSurvivalRate, weightedSurvivalRate);
112
113
olderSurvivalRate = weightedSurvivalRate;
114
}
115
}
116
Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_Exit(env->getLanguageVMThread());
117
}
118
119
120
void
121
MM_CompactGroupPersistentStats::calculateAgeGroupFractionsAtEdenBoundary(MM_EnvironmentVLHGC *env, U_64 ageInThisAgeGroup, U_64 *ageInThisCompactGroup, U_64 currentAge, U_64 allocatedSinceLastPGC, U_64 *edenFractionOfCompactGroup, U_64 *nonEdenFractionOfCompactGroup)
122
{
123
/* Find if age group is split by Eden boundary. */
124
U_64 nonEdenFractionOfAgeGroup = 0;
125
126
if (allocatedSinceLastPGC < currentAge) {
127
/* At least some part is out of eden */
128
if (currentAge - allocatedSinceLastPGC > ageInThisAgeGroup) {
129
/* whole group is out eden */
130
nonEdenFractionOfAgeGroup = ageInThisAgeGroup;
131
} else {
132
/* Less then full group is out of eden */
133
nonEdenFractionOfAgeGroup = currentAge - allocatedSinceLastPGC;
134
}
135
}
136
137
MM_GlobalAllocationManagerTarok *allocationManager = (MM_GlobalAllocationManagerTarok*)MM_GCExtensions::getExtensions(env)->globalAllocationManager;
138
UDATA managedAllocationContextCount = allocationManager->getManagedAllocationContextCount();
139
UDATA nonCommonAllocationContextCount = 1;
140
if (managedAllocationContextCount > 1) {
141
nonCommonAllocationContextCount = managedAllocationContextCount - 1;
142
}
143
144
/* we do not have historic info which fraction of this age group was allocated in this compact group; just take a fair share */
145
*nonEdenFractionOfCompactGroup = nonEdenFractionOfAgeGroup / nonCommonAllocationContextCount;
146
*ageInThisCompactGroup = *edenFractionOfCompactGroup + *nonEdenFractionOfCompactGroup;
147
148
}
149
150
void
151
MM_CompactGroupPersistentStats::updateProjectedSurvivalRate(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStatsArray, UDATA compactGroup)
152
{
153
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
154
const double newObservationWeight = 0.2;
155
MM_CompactGroupPersistentStats *persistentStats = &persistentStatsArray[compactGroup];
156
157
/* calculate the old historical survival rate */
158
UDATA liveBeforeCollect = persistentStats->_measuredLiveBytesBeforeCollectInCollectedSet;
159
160
if (liveBeforeCollect > 0) {
161
UDATA totalBytesBeforeCollect = persistentStats->_measuredLiveBytesBeforeCollectInGroup;
162
UDATA liveBytesInCollectedSetAfterCollect = persistentStats->_measuredLiveBytesAfterCollectInCollectedSet;
163
164
/* Note that this calculation doesn't try to limit the maximum impact of our new survival rate on the historic score
165
* which is consistent with the existing _rorStats. Since we always collect all of the nursery, this means that we
166
* will always replace the survival rate data of the nursery after each PGC
167
*/
168
double weightOfNewStats = 1.0;
169
if ((totalBytesBeforeCollect > 0) && (liveBeforeCollect < totalBytesBeforeCollect)) {
170
weightOfNewStats = (double)liveBeforeCollect / (double)totalBytesBeforeCollect;
171
Assert_MM_true(weightOfNewStats >= 0.0);
172
Assert_MM_true(weightOfNewStats <= 1.0);
173
}
174
double weightOfOldStats = 1.0 - weightOfNewStats;
175
176
/* Due to dark matter estimates the survival rate could appear to exceed 1.0 by a small amount, so cap it at 1.0. */
177
double thisSurvivalRate = OMR_MIN(1.0, (double)liveBytesInCollectedSetAfterCollect / (double)liveBeforeCollect);
178
Assert_MM_true(thisSurvivalRate >= 0.0);
179
180
double newSurvivalRate = (weightOfOldStats * persistentStats->_historicalSurvivalRate) + (weightOfNewStats * thisSurvivalRate);
181
Assert_MM_true(newSurvivalRate >= 0.0);
182
Assert_MM_true(newSurvivalRate <= 1.0);
183
184
persistentStats->_historicalSurvivalRate = newSurvivalRate;
185
}
186
187
/* Calculate the new projected survival rate */
188
UDATA projectedLiveBytesSelected = persistentStats->_projectedLiveBytesBeforeCollectInCollectedSet;
189
U_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();
190
if ((projectedLiveBytesSelected > 0) && (allocatedSinceLastPGC > 0)) {
191
UDATA projectedLiveBytesBefore = persistentStats->_projectedLiveBytesBeforeCollectInGroup;
192
UDATA measuredLiveBytesNotParticipating = (persistentStats->_measuredLiveBytesBeforeCollectInGroup - persistentStats->_measuredLiveBytesBeforeCollectInCollectedSet);
193
UDATA measuredLiveBytesAfter = (persistentStats->_measuredLiveBytesAfterCollectInCollectedSet + measuredLiveBytesNotParticipating);
194
double oldSurvivalRate = persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit;
195
/* By definition Instantaneous Survival Rate = (live bytes at the end of the current age group)/(live bytes at the end of the previous age group) per tarokAllocationAgeUnit
196
* (tarokAllocationAgeUnit defaults to Eden size, but could be far less than Eden size)
197
*/
198
199
/* We'll initially find survivorRate since last PGC and take out survivor rate of previous age groups to get survivor rate of current age group */
200
U_64 bytesRemaining = allocatedSinceLastPGC;
201
/* For Eden age groups, we'll take out "only" age groups since the moment they were created (they may not exist at previous PGC) */
202
/* TODO: currentAge should be average age (after GC) of collection set in this group */
203
U_64 currentAge = persistentStats->_maxAllocationAge;
204
U_64 maxAgeInThisAgeGroup = extensions->tarokAllocationAgeUnit;
205
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, compactGroup) > 0) {
206
maxAgeInThisAgeGroup = currentAge - persistentStatsArray[compactGroup - 1]._maxAllocationAge;
207
}
208
209
/* normalize for large age groups, larger than Eden */
210
U_64 ageInThisAgeGroup = OMR_MIN(maxAgeInThisAgeGroup, allocatedSinceLastPGC);
211
/* ageInThisCompactGroup essentially represents the amount of bytes allocated in this compact group out of this age group */
212
U_64 ageInThisCompactGroup = 0;
213
214
UDATA currentCompactGroup = compactGroup;
215
216
U_64 edenFractionOfCompactGroup = persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction;
217
U_64 nonEdenFractionOfCompactGroup = 0;
218
calculateAgeGroupFractionsAtEdenBoundary(env, ageInThisAgeGroup, &ageInThisCompactGroup, currentAge, allocatedSinceLastPGC, &edenFractionOfCompactGroup, &nonEdenFractionOfCompactGroup);
219
220
/* Calculate separately survivorRate for Eden and non Eden fractions of the age group */
221
double thisSurvivalRateForEdenFraction = (double)(measuredLiveBytesAfter - measuredLiveBytesNotParticipating) / ageInThisCompactGroup;
222
/* TODO: check cases when thisSurvivalRateForEdenFraction > 1.0. Should be completely or almost non-existent */
223
if (thisSurvivalRateForEdenFraction > 1.0){
224
thisSurvivalRateForEdenFraction = 1.0;
225
}
226
227
double thisSurvivalRateForNonEdenFraction = thisSurvivalRateForEdenFraction;
228
double projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction = (double)(persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSet - edenFractionOfCompactGroup);
229
Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_Entry(env->getLanguageVMThread(),
230
compactGroup,
231
(double)persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction / (1024*1024),
232
(double)persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSet / (1024*1024),
233
(double)(measuredLiveBytesAfter - measuredLiveBytesNotParticipating)/ (1024*1024),
234
(double)measuredLiveBytesAfter/ (1024*1024),
235
(double) measuredLiveBytesNotParticipating/ (1024*1024),
236
projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction/ (1024*1024));
237
Trc_MM_CompactGroupPersistentStats_calculateAgeGroupFractions(env->getLanguageVMThread(), persistentStats->_maxAllocationAge, maxAgeInThisAgeGroup, ageInThisAgeGroup, edenFractionOfCompactGroup, nonEdenFractionOfCompactGroup);
238
239
/* TODO: check cases when projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction < 0. Should be completely or almost non-existent */
240
if (projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction > 0.0) {
241
thisSurvivalRateForNonEdenFraction = thisSurvivalRateForEdenFraction * nonEdenFractionOfCompactGroup / projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction;
242
}
243
if (thisSurvivalRateForNonEdenFraction > 1.0){
244
thisSurvivalRateForNonEdenFraction = 1.0;
245
}
246
247
/* Skip all ageUnits in current compact group, to the maximum of what we allocated since last GC - this is where we want to calculate survivorRate */
248
bytesRemaining -= ageInThisAgeGroup;
249
currentAge -= ageInThisAgeGroup;
250
251
while (((bytesRemaining > 0) || (0 != edenFractionOfCompactGroup)) && (currentAge > 0)) {
252
/* check if we moved in next age group */
253
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) != 0) {
254
if (currentAge <= persistentStatsArray[currentCompactGroup - 1]._maxAllocationAge) {
255
currentCompactGroup -= 1;
256
}
257
}
258
259
double baseSurvivalRate = persistentStatsArray[currentCompactGroup]._projectedInstantaneousSurvivalRateThisPGCPerAgeUnit;
260
261
U_64 minAllocationAgeForThisCompactGroup = 0;
262
263
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {
264
minAllocationAgeForThisCompactGroup = persistentStatsArray[currentCompactGroup - 1]._maxAllocationAge;
265
}
266
267
U_64 ageInCurrentGroup = currentAge - minAllocationAgeForThisCompactGroup;
268
U_64 ageInCurrentGroupForEden = ageInCurrentGroup;
269
double ageUnitsInCurrentGroup = (double)ageInCurrentGroupForEden / extensions->tarokAllocationAgeUnit;
270
double survivalRate = pow(baseSurvivalRate, ageUnitsInCurrentGroup);
271
272
Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_eden(env->getLanguageVMThread(), thisSurvivalRateForEdenFraction, (double)currentAge/(1024*1024),
273
(double)bytesRemaining/(1024*1024), (double)ageInCurrentGroupForEden/(1024*1024), survivalRate, baseSurvivalRate, ageUnitsInCurrentGroup, currentCompactGroup);
274
thisSurvivalRateForEdenFraction = thisSurvivalRateForEdenFraction / survivalRate;
275
276
U_64 ageInCurrentGroupForNonEden = OMR_MIN(ageInCurrentGroup, bytesRemaining);
277
ageUnitsInCurrentGroup = (double)ageInCurrentGroupForNonEden / extensions->tarokAllocationAgeUnit;
278
survivalRate = pow(baseSurvivalRate, ageUnitsInCurrentGroup);
279
280
Assert_MM_true(0.0 < survivalRate);
281
Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_nonEden(env->getLanguageVMThread(), thisSurvivalRateForNonEdenFraction, (double)currentAge/(1024*1024),
282
(double)bytesRemaining/(1024*1024), (double)ageInCurrentGroupForNonEden/(1024*1024), survivalRate, baseSurvivalRate, ageUnitsInCurrentGroup, currentCompactGroup);
283
thisSurvivalRateForNonEdenFraction = thisSurvivalRateForNonEdenFraction / survivalRate;
284
285
Assert_MM_true(bytesRemaining >= ageInCurrentGroupForNonEden);
286
bytesRemaining -= ageInCurrentGroupForNonEden;
287
Assert_MM_true(currentAge >= ageInCurrentGroup);
288
currentAge -= ageInCurrentGroup;
289
}
290
291
if (thisSurvivalRateForEdenFraction > 1.0){
292
thisSurvivalRateForEdenFraction = 1.0;
293
}
294
if (thisSurvivalRateForNonEdenFraction > 1.0){
295
thisSurvivalRateForNonEdenFraction = 1.0;
296
}
297
298
/* Combine Eden and non-Eden survivor rate */
299
double weightedMeanSurvivalRate = 0.5;
300
if (0 != ageInThisCompactGroup) {
301
weightedMeanSurvivalRate = (thisSurvivalRateForEdenFraction * edenFractionOfCompactGroup + thisSurvivalRateForNonEdenFraction * nonEdenFractionOfCompactGroup) / ageInThisCompactGroup;
302
}
303
double ageUnitsInThisAgeGroup = (double)ageInThisAgeGroup / extensions->tarokAllocationAgeUnit;
304
double maxAgeUnitsInThisGroup = (double)maxAgeInThisAgeGroup / extensions->tarokAllocationAgeUnit;
305
306
double thisSurvivalRate = pow(weightedMeanSurvivalRate, 1/ageUnitsInThisAgeGroup);
307
308
Assert_MM_true(thisSurvivalRate >= 0.0);
309
Assert_MM_true(thisSurvivalRate <= 1.0);
310
311
/* Approximate zero survivor rate with a low non-zero number to avoid division with zero in future calculations */
312
if (0.0 == thisSurvivalRate) {
313
thisSurvivalRate = 0.01;
314
}
315
persistentStats->_projectedInstantaneousSurvivalRateThisPGCPerAgeUnit = thisSurvivalRate;
316
317
double observedWeight = 1.0;
318
if (projectedLiveBytesBefore > 0) {
319
observedWeight = newObservationWeight * (double)projectedLiveBytesSelected / (double)projectedLiveBytesBefore;
320
}
321
persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit = (observedWeight * thisSurvivalRate) + ((1.0 - observedWeight) * oldSurvivalRate);
322
persistentStats->_projectedInstantaneousSurvivalRate = pow(persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit, maxAgeUnitsInThisGroup);
323
324
Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_Exit(env->getLanguageVMThread(), compactGroup, thisSurvivalRateForEdenFraction, thisSurvivalRateForNonEdenFraction,
325
weightedMeanSurvivalRate, ageUnitsInThisAgeGroup, thisSurvivalRate, persistentStats->_projectedInstantaneousSurvivalRate, persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit);
326
}
327
}
328
329
void
330
MM_CompactGroupPersistentStats::deriveProjectedLiveBytesStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
331
{
332
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
333
GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);
334
MM_HeapRegionDescriptorVLHGC *region = NULL;
335
336
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
337
for (UDATA compactGroup= 0; compactGroup < compactGroupCount; compactGroup++) {
338
persistentStats[compactGroup]._projectedLiveBytes = 0;
339
persistentStats[compactGroup]._liveBytesAbsoluteDeviation = 0;
340
persistentStats[compactGroup]._regionCount = 0;
341
}
342
343
while (NULL != (region = regionIterator.nextRegion())) {
344
if(region->containsObjects()) {
345
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
346
UDATA projectedLiveBytes = region->_projectedLiveBytes;
347
IDATA liveBytesDeviation = region->_projectedLiveBytesDeviation;
348
persistentStats[compactGroup]._projectedLiveBytes += projectedLiveBytes;
349
persistentStats[compactGroup]._liveBytesAbsoluteDeviation += MM_Math::abs(liveBytesDeviation);
350
persistentStats[compactGroup]._regionCount += 1;
351
}
352
}
353
}
354
355
void
356
MM_CompactGroupPersistentStats::resetLiveBytesStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
357
{
358
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
359
for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {
360
/* clear the data we use to determine projected liveness, etc */
361
persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle = false;
362
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet = 0;
363
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInCollectedSet = 0;
364
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet = 0;
365
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction = 0;
366
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction = 0;
367
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup = 0;
368
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup = 0;
369
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup = 0;
370
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet = 0;
371
persistentStats[compactGroup]._measuredBytesCopiedFromGroupDuringCopyForward = 0;
372
persistentStats[compactGroup]._measuredBytesCopiedToGroupDuringCopyForward = 0;
373
persistentStats[compactGroup]._measuredAllocationAgeToGroupDuringCopyForward = 0;
374
persistentStats[compactGroup]._averageAllocationAgeToGroup = 0;
375
376
/* TODO: lpnguyen move this or rename this function (not a live bytes stat */
377
persistentStats[compactGroup]._regionsInRegionCollectionSetForPGC = 0;
378
}
379
}
380
381
void
382
MM_CompactGroupPersistentStats::calculateLiveBytesForRegion(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats, UDATA compactGroup, MM_HeapRegionDescriptorVLHGC *region, UDATA measuredLiveBytes, UDATA projectedLiveBytes)
383
{
384
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
385
U_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();
386
387
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet += measuredLiveBytes;
388
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInCollectedSet += projectedLiveBytes;
389
390
if (region->isEden()) {
391
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction += region->_projectedLiveBytesPreviousPGC;
392
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet += region->_projectedLiveBytesPreviousPGC;
393
} else {
394
395
U_64 boundary = 0;
396
U_64 maxAllocationAge = extensions->compactGroupPersistentStats[compactGroup]._maxAllocationAge;
397
U_64 minAllocationAge = 0;
398
399
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, compactGroup) > 0) {
400
minAllocationAge = extensions->compactGroupPersistentStats[compactGroup - 1]._maxAllocationAge;
401
}
402
U_64 ageSpan = maxAllocationAge - minAllocationAge;
403
/* while the region is non-Eden, the compact group it belongs to might cross Eden boundary */
404
U_64 nonEdenAgeSpan = 0;
405
/* Only the upper portion of the non-Eden span is a good representative. About to calculate the size of the sample */
406
U_64 sampleSpan = 0;
407
408
/* We use a premise: given a point of time m (expressed in MB allocated), liveness of objects are constant between m/expBase and m.
409
* For non, linear aging this range (m/expBase,m) can span multiple age groups, which may have different liveness.
410
*/
411
412
if (maxAllocationAge > allocatedSinceLastPGC) {
413
U_64 oldestAgePointObjectsCameFrom = maxAllocationAge - allocatedSinceLastPGC;
414
sampleSpan = (U_64) ((double)(oldestAgePointObjectsCameFrom) / extensions->tarokAllocationAgeExponentBase);
415
/* between oldestAgePointObjectsCameFrom - sampleSpan and oldestAgePointObjectsCameFrom, we consider objects had same liveness. */
416
/* however, object are already forward-aged at the end of previous PGC, so we are talking about (maxAllocationAge - sampleSpan, maxAllocationAge) span */
417
boundary = maxAllocationAge - sampleSpan;
418
nonEdenAgeSpan = OMR_MIN(ageSpan, maxAllocationAge - allocatedSinceLastPGC);
419
}
420
421
double nonEdenSpanExpandRatio = 1.0;
422
if (maxAllocationAge > allocatedSinceLastPGC + sampleSpan) {
423
nonEdenSpanExpandRatio = (double)nonEdenAgeSpan / (maxAllocationAge - allocatedSinceLastPGC - sampleSpan);
424
}
425
426
UDATA liveBytesAboveBoundary = 0;
427
if (region->getAllocationAge() >= boundary) {
428
liveBytesAboveBoundary = region->_projectedLiveBytesPreviousPGC;
429
430
if (region->getLowerAgeBound() < boundary) {
431
/* not a whole region is above boundary */
432
433
/* first calculated the fraction of objects below average age */
434
UDATA liveBytesBelowAverageAge = (UDATA)(region->_projectedLiveBytesPreviousPGC
435
* (region->getUpperAgeBound() - region->getAllocationAge())
436
/ (region->getUpperAgeBound() - region->getLowerAgeBound()));
437
438
/* now, find the fraction of below boundary */
439
UDATA liveBytesBelowBoundary = (UDATA)(liveBytesBelowAverageAge
440
* (boundary - region->getLowerAgeBound())
441
/ (region->getAllocationAge() - region->getLowerAgeBound()));
442
443
liveBytesAboveBoundary -= liveBytesBelowBoundary;
444
445
}
446
447
} else {
448
if (region->getUpperAgeBound() > boundary) {
449
/* at least a fraction of the region is above boundary */
450
451
/* first calculated the fraction of objects above average age */
452
UDATA liveBytesAboveAverageAge = (UDATA)(region->_projectedLiveBytesPreviousPGC
453
* (region->getAllocationAge() - region->getLowerAgeBound())
454
/ (region->getUpperAgeBound() - region->getLowerAgeBound()));
455
456
/* now, find the fraction of above boundary */
457
liveBytesAboveBoundary = (UDATA)(liveBytesAboveAverageAge
458
* (region->getUpperAgeBound() - boundary)
459
/ (region->getUpperAgeBound() - region->getAllocationAge()));
460
}
461
462
}
463
464
liveBytesAboveBoundary = (UDATA)(nonEdenSpanExpandRatio * liveBytesAboveBoundary);
465
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction += liveBytesAboveBoundary;
466
persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet += liveBytesAboveBoundary;
467
}
468
}
469
470
471
void
472
MM_CompactGroupPersistentStats::updateStatsBeforeCopyForward(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
473
{
474
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
475
MM_HeapRegionManager *regionManager = extensions->heapRegionManager;
476
UDATA regionSize = regionManager->getRegionSize();
477
GC_HeapRegionIteratorVLHGC regionIterator(regionManager);
478
MM_HeapRegionDescriptorVLHGC *region = NULL;
479
480
while(NULL != (region = regionIterator.nextRegion())) {
481
if (region->containsObjects()) {
482
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
483
484
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
485
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
486
Assert_MM_true(completeFreeMemory <= regionSize);
487
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
488
UDATA projectedLiveBytes = region->_projectedLiveBytes;
489
490
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;
491
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;
492
if (region->_markData._shouldMark) {
493
calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);
494
}
495
}
496
}
497
}
498
}
499
500
void
501
MM_CompactGroupPersistentStats::updateStatsAfterCopyForward(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
502
{
503
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
504
for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {
505
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
506
UDATA liveBeforeCollect = persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet;
507
508
if (liveBeforeCollect > 0) {
509
UDATA totalBytesBeforeCollect = persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup;
510
UDATA measuredNonParticipatingLiveBytes = (totalBytesBeforeCollect - liveBeforeCollect);
511
UDATA totalBytesAfterCollect = (persistentStats[compactGroup]._measuredBytesCopiedFromGroupDuringCopyForward + measuredNonParticipatingLiveBytes);
512
513
Assert_MM_true(totalBytesBeforeCollect >= liveBeforeCollect);
514
515
Assert_MM_true(totalBytesAfterCollect >= measuredNonParticipatingLiveBytes);
516
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup = totalBytesAfterCollect;
517
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet = totalBytesAfterCollect - measuredNonParticipatingLiveBytes;
518
}
519
}
520
}
521
522
updateStatsAfterCollectionOperation(env, persistentStats);
523
}
524
525
void
526
MM_CompactGroupPersistentStats::updateStatsBeforeSweep(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
527
{
528
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
529
MM_HeapRegionManager *regionManager = extensions->heapRegionManager;
530
UDATA regionSize = regionManager->getRegionSize();
531
GC_HeapRegionIteratorVLHGC regionIterator(regionManager);
532
MM_HeapRegionDescriptorVLHGC *region = NULL;
533
534
while(NULL != (region = regionIterator.nextRegion())) {
535
if (region->containsObjects()) {
536
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
537
538
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
539
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
540
Assert_MM_true(completeFreeMemory <= regionSize);
541
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
542
UDATA projectedLiveBytes = region->_projectedLiveBytes;
543
544
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;
545
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;
546
if (!region->_sweepData._alreadySwept) {
547
calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);
548
}
549
}
550
}
551
}
552
}
553
554
void
555
MM_CompactGroupPersistentStats::updateStatsAfterSweep(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
556
{
557
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
558
MM_HeapRegionManager *regionManager = extensions->heapRegionManager;
559
UDATA regionSize = regionManager->getRegionSize();
560
GC_HeapRegionIteratorVLHGC regionIterator(regionManager, MM_HeapRegionDescriptor::ALL);
561
MM_HeapRegionDescriptorVLHGC *region = NULL;
562
563
while(NULL != (region = regionIterator.nextRegion())) {
564
if (region->containsObjects()) {
565
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
566
567
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
568
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
569
Assert_MM_true(completeFreeMemory <= regionSize);
570
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
571
572
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup += measuredLiveBytes;
573
if (!region->_sweepData._alreadySwept) {
574
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet += measuredLiveBytes;
575
}
576
}
577
}
578
}
579
updateStatsAfterCollectionOperation(env, persistentStats);
580
}
581
582
void
583
MM_CompactGroupPersistentStats::updateStatsBeforeCompact(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
584
{
585
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
586
MM_HeapRegionManager *regionManager = extensions->heapRegionManager;
587
UDATA regionSize = regionManager->getRegionSize();
588
GC_HeapRegionIteratorVLHGC regionIterator(regionManager);
589
MM_HeapRegionDescriptorVLHGC *region = NULL;
590
591
while(NULL != (region = regionIterator.nextRegion())) {
592
if (region->containsObjects()) {
593
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
594
595
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
596
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
597
Assert_MM_true(completeFreeMemory <= regionSize);
598
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
599
UDATA projectedLiveBytes = region->_projectedLiveBytes;
600
601
persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;
602
persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;
603
if (region->_compactData._shouldCompact) {
604
calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);
605
}
606
}
607
}
608
}
609
}
610
611
void
612
MM_CompactGroupPersistentStats::updateStatsAfterCompact(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
613
{
614
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
615
MM_HeapRegionManager *regionManager = extensions->heapRegionManager;
616
UDATA regionSize = regionManager->getRegionSize();
617
GC_HeapRegionIteratorVLHGC regionIterator(regionManager, MM_HeapRegionDescriptor::ALL);
618
MM_HeapRegionDescriptorVLHGC *region = NULL;
619
620
while(NULL != (region = regionIterator.nextRegion())) {
621
if (region->containsObjects()) {
622
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
623
624
if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
625
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
626
Assert_MM_true(completeFreeMemory <= regionSize);
627
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
628
629
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup += measuredLiveBytes;
630
if (region->_compactData._shouldCompact) {
631
persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet += measuredLiveBytes;
632
}
633
}
634
}
635
}
636
updateStatsAfterCollectionOperation(env, persistentStats);
637
}
638
639
void
640
MM_CompactGroupPersistentStats::initProjectedLiveBytes(MM_EnvironmentVLHGC *env)
641
{
642
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
643
GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);
644
MM_HeapRegionDescriptorVLHGC *region = NULL;
645
UDATA regionSize = extensions->heapRegionManager->getRegionSize();
646
647
while (NULL != (region = regionIterator.nextRegion())) {
648
/* UDATA_MAX has a special meaning of 'uninitialized' */
649
if(region->containsObjects() && (UDATA_MAX == region->_projectedLiveBytes)) {
650
UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();
651
Assert_MM_true(completeFreeMemory <= regionSize);
652
UDATA measuredLiveBytes = regionSize - completeFreeMemory;
653
region->_projectedLiveBytes = measuredLiveBytes;
654
}
655
}
656
}
657
658
void
659
MM_CompactGroupPersistentStats::updateStatsAfterCollectionOperation(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
660
{
661
bool compactGroupUpdated = false;
662
UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);
663
for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {
664
if (persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet > 0) {
665
if(!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {
666
persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle = true;
667
updateProjectedSurvivalRate(env, persistentStats, compactGroup);
668
compactGroupUpdated = true;
669
}
670
}
671
}
672
673
if (compactGroupUpdated) {
674
deriveWeightedSurvivalRates(env, persistentStats);
675
}
676
}
677
678
void
679
MM_CompactGroupPersistentStats::decayProjectedLiveBytesForRegions(MM_EnvironmentVLHGC *env)
680
{
681
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
682
GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);
683
MM_HeapRegionDescriptorVLHGC *region = NULL;
684
MM_CompactGroupPersistentStats * persistentStats = extensions->compactGroupPersistentStats;
685
686
while (NULL != (region = regionIterator.nextRegion())) {
687
if(region->containsObjects()) {
688
/* before applying decay, take a snapshot of projectedLiveBytes used later for survivor rate calculation */
689
region->_projectedLiveBytesPreviousPGC = region->_projectedLiveBytes;
690
// TODO amicic: do we need to do on regions in eden (projectedLiveBytes is measuredLiveBytes)?
691
692
I_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();
693
UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);
694
695
I_64 currentAge = (I_64)region->getAllocationAge();
696
I_64 bytesRemaining = allocatedSinceLastPGC;
697
UDATA currentCompactGroup = compactGroup;
698
699
while ((bytesRemaining > 0) && (currentAge > 0)) {
700
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {
701
if ((currentAge <= (IDATA)persistentStats[currentCompactGroup - 1]._maxAllocationAge)) {
702
currentCompactGroup -= 1;
703
}
704
}
705
706
double baseSurvivalRate = persistentStats[currentCompactGroup]._projectedInstantaneousSurvivalRatePerAgeUnit;
707
708
U_64 minAllocationAgeForThisCompactGroup = 0;
709
710
if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {
711
minAllocationAgeForThisCompactGroup = persistentStats[currentCompactGroup - 1]._maxAllocationAge;
712
}
713
714
U_64 ageInThisGroup = OMR_MIN((U_64)bytesRemaining, (U_64)currentAge - minAllocationAgeForThisCompactGroup);
715
double ageUnitsInThisGroup = (double)ageInThisGroup / extensions->tarokAllocationAgeUnit;
716
double survivalRate = pow(baseSurvivalRate, ageUnitsInThisGroup);
717
718
UDATA oldProjectedLiveBytes = region->_projectedLiveBytes;
719
region->_projectedLiveBytes = (UDATA) ((double)oldProjectedLiveBytes * survivalRate);
720
721
Trc_MM_CompactGroupPersistentStats_decayProjectedLiveBytesForRegions(env->getLanguageVMThread(), extensions->heapRegionManager->mapDescriptorToRegionTableIndex(region),
722
(double)oldProjectedLiveBytes / (1024*1024), (double)region->_projectedLiveBytes / (1024*1024), compactGroup,
723
(double)bytesRemaining / (1024*1024), (double)currentAge / (1024*1024), survivalRate, baseSurvivalRate, ageUnitsInThisGroup, currentCompactGroup);
724
725
bytesRemaining -= ageInThisGroup;
726
currentAge -= ageInThisGroup;
727
}
728
}
729
}
730
}
731
732
void
733
MM_CompactGroupPersistentStats::updateStatsBeforeCollect(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)
734
{
735
resetLiveBytesStats(env, persistentStats);
736
initProjectedLiveBytes(env);
737
decayProjectedLiveBytesForRegions(env);
738
}
739
740