Path: blob/master/runtime/gc_vlhgc/CompactGroupPersistentStats.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include <string.h>23#include <math.h>242526#include "CompactGroupPersistentStats.hpp"2728#include "AllocationContextTarok.hpp"29#include "CompactGroupManager.hpp"30#include "EnvironmentVLHGC.hpp"31#include "GCExtensions.hpp"32#include "GlobalAllocationManagerTarok.hpp"33#include "HeapRegionIteratorVLHGC.hpp"34#include "HeapRegionManager.hpp"35#include "IncrementalGenerationalGC.hpp"36#include "Math.hpp"3738MM_CompactGroupPersistentStats *39MM_CompactGroupPersistentStats::allocateCompactGroupPersistentStats(MM_EnvironmentVLHGC *env)40{41MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);42UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);43UDATA persistentStatsAllocationSize = sizeof(MM_CompactGroupPersistentStats) * compactGroupCount;4445MM_CompactGroupPersistentStats * result = (MM_CompactGroupPersistentStats *)extensions->getForge()->allocate(persistentStatsAllocationSize, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());46if (NULL != result) {47memset(result, 0x0, persistentStatsAllocationSize);48for (UDATA i = 0; i < compactGroupCount; i++) {49result[i]._historicalSurvivalRate = 1.0;50result[i]._weightedSurvivalRate = 1.0;51result[i]._projectedInstantaneousSurvivalRate = 1.0;52result[i]._projectedInstantaneousSurvivalRatePerAgeUnit = 1.0;53result[i]._projectedInstantaneousSurvivalRateThisPGCPerAgeUnit = 1.0;54result[i]._projectedLiveBytes = 0;55result[i]._liveBytesAbsoluteDeviation = 0;56result[i]._regionCount = 0;57result[i]._statsHaveBeenUpdatedThisCycle = false;58/* this is not really stats, but a constant; calculate only if unit is set */59if (0 != extensions->tarokAllocationAgeUnit) {60UDATA ageGroup = MM_CompactGroupManager::getRegionAgeFromGroup(env, i);61if (ageGroup != extensions->tarokRegionMaxAge) {62result[i]._maxAllocationAge = MM_CompactGroupManager::calculateMaximumAllocationAge(env, ageGroup + 1);63} else {64result[i]._maxAllocationAge = UDATA_MAX;65}66}67}68}69return result;70}7172void73MM_CompactGroupPersistentStats::killCompactGroupPersistentStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)74{75MM_GCExtensions::getExtensions(env)->getForge()->free(persistentStats);76}777879void80MM_CompactGroupPersistentStats::deriveWeightedSurvivalRates(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)81{82/* this weight is completely arbitrary */83const double olderWeight = 0.7;84const double thisWeight = 1.0 - olderWeight;85Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_Entry(env->getLanguageVMThread(), olderWeight);8687MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);88MM_GlobalAllocationManagerTarok *allocationManager = (MM_GlobalAllocationManagerTarok*)extensions->globalAllocationManager;8990UDATA regionMaxAge = extensions->tarokRegionMaxAge;91UDATA managedAllocationContextCount = allocationManager->getManagedAllocationContextCount();92for (UDATA contextIndex = 0; contextIndex < managedAllocationContextCount; contextIndex++) {93MM_AllocationContextTarok *context = allocationManager->getAllocationContextByIndex(contextIndex);94double olderSurvivalRate = 1.0;9596/* process the compact groups from oldest to youngest (note that the for loop relies on integer-underflow) */97for (UDATA age = regionMaxAge; age <= regionMaxAge; age--) {98UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumberForAge(env, age, context);99100double thisSurvivalRate = persistentStats[compactGroup]._historicalSurvivalRate;101double weightedSurvivalRate = (olderWeight * olderSurvivalRate) + (thisWeight * thisSurvivalRate);102/* the historical rate may decrease the apparent survival rate but isn't permitted to increase it */103weightedSurvivalRate = OMR_MIN(weightedSurvivalRate, thisSurvivalRate);104105Assert_MM_true(0.0 <= weightedSurvivalRate);106Assert_MM_true(1.0 >= weightedSurvivalRate);107108persistentStats[compactGroup]._weightedSurvivalRate = weightedSurvivalRate;109110Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_group(env->getLanguageVMThread(), contextIndex, age, thisSurvivalRate, weightedSurvivalRate);111112olderSurvivalRate = weightedSurvivalRate;113}114}115Trc_MM_CompactGroupPersistentStats_deriveWeightedSurvivalRates_Exit(env->getLanguageVMThread());116}117118119void120MM_CompactGroupPersistentStats::calculateAgeGroupFractionsAtEdenBoundary(MM_EnvironmentVLHGC *env, U_64 ageInThisAgeGroup, U_64 *ageInThisCompactGroup, U_64 currentAge, U_64 allocatedSinceLastPGC, U_64 *edenFractionOfCompactGroup, U_64 *nonEdenFractionOfCompactGroup)121{122/* Find if age group is split by Eden boundary. */123U_64 nonEdenFractionOfAgeGroup = 0;124125if (allocatedSinceLastPGC < currentAge) {126/* At least some part is out of eden */127if (currentAge - allocatedSinceLastPGC > ageInThisAgeGroup) {128/* whole group is out eden */129nonEdenFractionOfAgeGroup = ageInThisAgeGroup;130} else {131/* Less then full group is out of eden */132nonEdenFractionOfAgeGroup = currentAge - allocatedSinceLastPGC;133}134}135136MM_GlobalAllocationManagerTarok *allocationManager = (MM_GlobalAllocationManagerTarok*)MM_GCExtensions::getExtensions(env)->globalAllocationManager;137UDATA managedAllocationContextCount = allocationManager->getManagedAllocationContextCount();138UDATA nonCommonAllocationContextCount = 1;139if (managedAllocationContextCount > 1) {140nonCommonAllocationContextCount = managedAllocationContextCount - 1;141}142143/* we do not have historic info which fraction of this age group was allocated in this compact group; just take a fair share */144*nonEdenFractionOfCompactGroup = nonEdenFractionOfAgeGroup / nonCommonAllocationContextCount;145*ageInThisCompactGroup = *edenFractionOfCompactGroup + *nonEdenFractionOfCompactGroup;146147}148149void150MM_CompactGroupPersistentStats::updateProjectedSurvivalRate(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStatsArray, UDATA compactGroup)151{152MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);153const double newObservationWeight = 0.2;154MM_CompactGroupPersistentStats *persistentStats = &persistentStatsArray[compactGroup];155156/* calculate the old historical survival rate */157UDATA liveBeforeCollect = persistentStats->_measuredLiveBytesBeforeCollectInCollectedSet;158159if (liveBeforeCollect > 0) {160UDATA totalBytesBeforeCollect = persistentStats->_measuredLiveBytesBeforeCollectInGroup;161UDATA liveBytesInCollectedSetAfterCollect = persistentStats->_measuredLiveBytesAfterCollectInCollectedSet;162163/* Note that this calculation doesn't try to limit the maximum impact of our new survival rate on the historic score164* which is consistent with the existing _rorStats. Since we always collect all of the nursery, this means that we165* will always replace the survival rate data of the nursery after each PGC166*/167double weightOfNewStats = 1.0;168if ((totalBytesBeforeCollect > 0) && (liveBeforeCollect < totalBytesBeforeCollect)) {169weightOfNewStats = (double)liveBeforeCollect / (double)totalBytesBeforeCollect;170Assert_MM_true(weightOfNewStats >= 0.0);171Assert_MM_true(weightOfNewStats <= 1.0);172}173double weightOfOldStats = 1.0 - weightOfNewStats;174175/* Due to dark matter estimates the survival rate could appear to exceed 1.0 by a small amount, so cap it at 1.0. */176double thisSurvivalRate = OMR_MIN(1.0, (double)liveBytesInCollectedSetAfterCollect / (double)liveBeforeCollect);177Assert_MM_true(thisSurvivalRate >= 0.0);178179double newSurvivalRate = (weightOfOldStats * persistentStats->_historicalSurvivalRate) + (weightOfNewStats * thisSurvivalRate);180Assert_MM_true(newSurvivalRate >= 0.0);181Assert_MM_true(newSurvivalRate <= 1.0);182183persistentStats->_historicalSurvivalRate = newSurvivalRate;184}185186/* Calculate the new projected survival rate */187UDATA projectedLiveBytesSelected = persistentStats->_projectedLiveBytesBeforeCollectInCollectedSet;188U_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();189if ((projectedLiveBytesSelected > 0) && (allocatedSinceLastPGC > 0)) {190UDATA projectedLiveBytesBefore = persistentStats->_projectedLiveBytesBeforeCollectInGroup;191UDATA measuredLiveBytesNotParticipating = (persistentStats->_measuredLiveBytesBeforeCollectInGroup - persistentStats->_measuredLiveBytesBeforeCollectInCollectedSet);192UDATA measuredLiveBytesAfter = (persistentStats->_measuredLiveBytesAfterCollectInCollectedSet + measuredLiveBytesNotParticipating);193double oldSurvivalRate = persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit;194/* 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 tarokAllocationAgeUnit195* (tarokAllocationAgeUnit defaults to Eden size, but could be far less than Eden size)196*/197198/* 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 */199U_64 bytesRemaining = allocatedSinceLastPGC;200/* For Eden age groups, we'll take out "only" age groups since the moment they were created (they may not exist at previous PGC) */201/* TODO: currentAge should be average age (after GC) of collection set in this group */202U_64 currentAge = persistentStats->_maxAllocationAge;203U_64 maxAgeInThisAgeGroup = extensions->tarokAllocationAgeUnit;204if (MM_CompactGroupManager::getRegionAgeFromGroup(env, compactGroup) > 0) {205maxAgeInThisAgeGroup = currentAge - persistentStatsArray[compactGroup - 1]._maxAllocationAge;206}207208/* normalize for large age groups, larger than Eden */209U_64 ageInThisAgeGroup = OMR_MIN(maxAgeInThisAgeGroup, allocatedSinceLastPGC);210/* ageInThisCompactGroup essentially represents the amount of bytes allocated in this compact group out of this age group */211U_64 ageInThisCompactGroup = 0;212213UDATA currentCompactGroup = compactGroup;214215U_64 edenFractionOfCompactGroup = persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction;216U_64 nonEdenFractionOfCompactGroup = 0;217calculateAgeGroupFractionsAtEdenBoundary(env, ageInThisAgeGroup, &ageInThisCompactGroup, currentAge, allocatedSinceLastPGC, &edenFractionOfCompactGroup, &nonEdenFractionOfCompactGroup);218219/* Calculate separately survivorRate for Eden and non Eden fractions of the age group */220double thisSurvivalRateForEdenFraction = (double)(measuredLiveBytesAfter - measuredLiveBytesNotParticipating) / ageInThisCompactGroup;221/* TODO: check cases when thisSurvivalRateForEdenFraction > 1.0. Should be completely or almost non-existent */222if (thisSurvivalRateForEdenFraction > 1.0){223thisSurvivalRateForEdenFraction = 1.0;224}225226double thisSurvivalRateForNonEdenFraction = thisSurvivalRateForEdenFraction;227double projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction = (double)(persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSet - edenFractionOfCompactGroup);228Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_Entry(env->getLanguageVMThread(),229compactGroup,230(double)persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction / (1024*1024),231(double)persistentStats->_projectedLiveBytesAfterPreviousPGCInCollectedSet / (1024*1024),232(double)(measuredLiveBytesAfter - measuredLiveBytesNotParticipating)/ (1024*1024),233(double)measuredLiveBytesAfter/ (1024*1024),234(double) measuredLiveBytesNotParticipating/ (1024*1024),235projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction/ (1024*1024));236Trc_MM_CompactGroupPersistentStats_calculateAgeGroupFractions(env->getLanguageVMThread(), persistentStats->_maxAllocationAge, maxAgeInThisAgeGroup, ageInThisAgeGroup, edenFractionOfCompactGroup, nonEdenFractionOfCompactGroup);237238/* TODO: check cases when projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction < 0. Should be completely or almost non-existent */239if (projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction > 0.0) {240thisSurvivalRateForNonEdenFraction = thisSurvivalRateForEdenFraction * nonEdenFractionOfCompactGroup / projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction;241}242if (thisSurvivalRateForNonEdenFraction > 1.0){243thisSurvivalRateForNonEdenFraction = 1.0;244}245246/* 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 */247bytesRemaining -= ageInThisAgeGroup;248currentAge -= ageInThisAgeGroup;249250while (((bytesRemaining > 0) || (0 != edenFractionOfCompactGroup)) && (currentAge > 0)) {251/* check if we moved in next age group */252if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) != 0) {253if (currentAge <= persistentStatsArray[currentCompactGroup - 1]._maxAllocationAge) {254currentCompactGroup -= 1;255}256}257258double baseSurvivalRate = persistentStatsArray[currentCompactGroup]._projectedInstantaneousSurvivalRateThisPGCPerAgeUnit;259260U_64 minAllocationAgeForThisCompactGroup = 0;261262if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {263minAllocationAgeForThisCompactGroup = persistentStatsArray[currentCompactGroup - 1]._maxAllocationAge;264}265266U_64 ageInCurrentGroup = currentAge - minAllocationAgeForThisCompactGroup;267U_64 ageInCurrentGroupForEden = ageInCurrentGroup;268double ageUnitsInCurrentGroup = (double)ageInCurrentGroupForEden / extensions->tarokAllocationAgeUnit;269double survivalRate = pow(baseSurvivalRate, ageUnitsInCurrentGroup);270271Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_eden(env->getLanguageVMThread(), thisSurvivalRateForEdenFraction, (double)currentAge/(1024*1024),272(double)bytesRemaining/(1024*1024), (double)ageInCurrentGroupForEden/(1024*1024), survivalRate, baseSurvivalRate, ageUnitsInCurrentGroup, currentCompactGroup);273thisSurvivalRateForEdenFraction = thisSurvivalRateForEdenFraction / survivalRate;274275U_64 ageInCurrentGroupForNonEden = OMR_MIN(ageInCurrentGroup, bytesRemaining);276ageUnitsInCurrentGroup = (double)ageInCurrentGroupForNonEden / extensions->tarokAllocationAgeUnit;277survivalRate = pow(baseSurvivalRate, ageUnitsInCurrentGroup);278279Assert_MM_true(0.0 < survivalRate);280Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_nonEden(env->getLanguageVMThread(), thisSurvivalRateForNonEdenFraction, (double)currentAge/(1024*1024),281(double)bytesRemaining/(1024*1024), (double)ageInCurrentGroupForNonEden/(1024*1024), survivalRate, baseSurvivalRate, ageUnitsInCurrentGroup, currentCompactGroup);282thisSurvivalRateForNonEdenFraction = thisSurvivalRateForNonEdenFraction / survivalRate;283284Assert_MM_true(bytesRemaining >= ageInCurrentGroupForNonEden);285bytesRemaining -= ageInCurrentGroupForNonEden;286Assert_MM_true(currentAge >= ageInCurrentGroup);287currentAge -= ageInCurrentGroup;288}289290if (thisSurvivalRateForEdenFraction > 1.0){291thisSurvivalRateForEdenFraction = 1.0;292}293if (thisSurvivalRateForNonEdenFraction > 1.0){294thisSurvivalRateForNonEdenFraction = 1.0;295}296297/* Combine Eden and non-Eden survivor rate */298double weightedMeanSurvivalRate = 0.5;299if (0 != ageInThisCompactGroup) {300weightedMeanSurvivalRate = (thisSurvivalRateForEdenFraction * edenFractionOfCompactGroup + thisSurvivalRateForNonEdenFraction * nonEdenFractionOfCompactGroup) / ageInThisCompactGroup;301}302double ageUnitsInThisAgeGroup = (double)ageInThisAgeGroup / extensions->tarokAllocationAgeUnit;303double maxAgeUnitsInThisGroup = (double)maxAgeInThisAgeGroup / extensions->tarokAllocationAgeUnit;304305double thisSurvivalRate = pow(weightedMeanSurvivalRate, 1/ageUnitsInThisAgeGroup);306307Assert_MM_true(thisSurvivalRate >= 0.0);308Assert_MM_true(thisSurvivalRate <= 1.0);309310/* Approximate zero survivor rate with a low non-zero number to avoid division with zero in future calculations */311if (0.0 == thisSurvivalRate) {312thisSurvivalRate = 0.01;313}314persistentStats->_projectedInstantaneousSurvivalRateThisPGCPerAgeUnit = thisSurvivalRate;315316double observedWeight = 1.0;317if (projectedLiveBytesBefore > 0) {318observedWeight = newObservationWeight * (double)projectedLiveBytesSelected / (double)projectedLiveBytesBefore;319}320persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit = (observedWeight * thisSurvivalRate) + ((1.0 - observedWeight) * oldSurvivalRate);321persistentStats->_projectedInstantaneousSurvivalRate = pow(persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit, maxAgeUnitsInThisGroup);322323Trc_MM_CompactGroupPersistentStats_updateProjectedSurvivalRate_Exit(env->getLanguageVMThread(), compactGroup, thisSurvivalRateForEdenFraction, thisSurvivalRateForNonEdenFraction,324weightedMeanSurvivalRate, ageUnitsInThisAgeGroup, thisSurvivalRate, persistentStats->_projectedInstantaneousSurvivalRate, persistentStats->_projectedInstantaneousSurvivalRatePerAgeUnit);325}326}327328void329MM_CompactGroupPersistentStats::deriveProjectedLiveBytesStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)330{331MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);332GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);333MM_HeapRegionDescriptorVLHGC *region = NULL;334335UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);336for (UDATA compactGroup= 0; compactGroup < compactGroupCount; compactGroup++) {337persistentStats[compactGroup]._projectedLiveBytes = 0;338persistentStats[compactGroup]._liveBytesAbsoluteDeviation = 0;339persistentStats[compactGroup]._regionCount = 0;340}341342while (NULL != (region = regionIterator.nextRegion())) {343if(region->containsObjects()) {344UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);345UDATA projectedLiveBytes = region->_projectedLiveBytes;346IDATA liveBytesDeviation = region->_projectedLiveBytesDeviation;347persistentStats[compactGroup]._projectedLiveBytes += projectedLiveBytes;348persistentStats[compactGroup]._liveBytesAbsoluteDeviation += MM_Math::abs(liveBytesDeviation);349persistentStats[compactGroup]._regionCount += 1;350}351}352}353354void355MM_CompactGroupPersistentStats::resetLiveBytesStats(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)356{357UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);358for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {359/* clear the data we use to determine projected liveness, etc */360persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle = false;361persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet = 0;362persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInCollectedSet = 0;363persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet = 0;364persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction = 0;365persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction = 0;366persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup = 0;367persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup = 0;368persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup = 0;369persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet = 0;370persistentStats[compactGroup]._measuredBytesCopiedFromGroupDuringCopyForward = 0;371persistentStats[compactGroup]._measuredBytesCopiedToGroupDuringCopyForward = 0;372persistentStats[compactGroup]._measuredAllocationAgeToGroupDuringCopyForward = 0;373persistentStats[compactGroup]._averageAllocationAgeToGroup = 0;374375/* TODO: lpnguyen move this or rename this function (not a live bytes stat */376persistentStats[compactGroup]._regionsInRegionCollectionSetForPGC = 0;377}378}379380void381MM_CompactGroupPersistentStats::calculateLiveBytesForRegion(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats, UDATA compactGroup, MM_HeapRegionDescriptorVLHGC *region, UDATA measuredLiveBytes, UDATA projectedLiveBytes)382{383MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);384U_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();385386persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet += measuredLiveBytes;387persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInCollectedSet += projectedLiveBytes;388389if (region->isEden()) {390persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForEdenFraction += region->_projectedLiveBytesPreviousPGC;391persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet += region->_projectedLiveBytesPreviousPGC;392} else {393394U_64 boundary = 0;395U_64 maxAllocationAge = extensions->compactGroupPersistentStats[compactGroup]._maxAllocationAge;396U_64 minAllocationAge = 0;397398if (MM_CompactGroupManager::getRegionAgeFromGroup(env, compactGroup) > 0) {399minAllocationAge = extensions->compactGroupPersistentStats[compactGroup - 1]._maxAllocationAge;400}401U_64 ageSpan = maxAllocationAge - minAllocationAge;402/* while the region is non-Eden, the compact group it belongs to might cross Eden boundary */403U_64 nonEdenAgeSpan = 0;404/* Only the upper portion of the non-Eden span is a good representative. About to calculate the size of the sample */405U_64 sampleSpan = 0;406407/* We use a premise: given a point of time m (expressed in MB allocated), liveness of objects are constant between m/expBase and m.408* For non, linear aging this range (m/expBase,m) can span multiple age groups, which may have different liveness.409*/410411if (maxAllocationAge > allocatedSinceLastPGC) {412U_64 oldestAgePointObjectsCameFrom = maxAllocationAge - allocatedSinceLastPGC;413sampleSpan = (U_64) ((double)(oldestAgePointObjectsCameFrom) / extensions->tarokAllocationAgeExponentBase);414/* between oldestAgePointObjectsCameFrom - sampleSpan and oldestAgePointObjectsCameFrom, we consider objects had same liveness. */415/* however, object are already forward-aged at the end of previous PGC, so we are talking about (maxAllocationAge - sampleSpan, maxAllocationAge) span */416boundary = maxAllocationAge - sampleSpan;417nonEdenAgeSpan = OMR_MIN(ageSpan, maxAllocationAge - allocatedSinceLastPGC);418}419420double nonEdenSpanExpandRatio = 1.0;421if (maxAllocationAge > allocatedSinceLastPGC + sampleSpan) {422nonEdenSpanExpandRatio = (double)nonEdenAgeSpan / (maxAllocationAge - allocatedSinceLastPGC - sampleSpan);423}424425UDATA liveBytesAboveBoundary = 0;426if (region->getAllocationAge() >= boundary) {427liveBytesAboveBoundary = region->_projectedLiveBytesPreviousPGC;428429if (region->getLowerAgeBound() < boundary) {430/* not a whole region is above boundary */431432/* first calculated the fraction of objects below average age */433UDATA liveBytesBelowAverageAge = (UDATA)(region->_projectedLiveBytesPreviousPGC434* (region->getUpperAgeBound() - region->getAllocationAge())435/ (region->getUpperAgeBound() - region->getLowerAgeBound()));436437/* now, find the fraction of below boundary */438UDATA liveBytesBelowBoundary = (UDATA)(liveBytesBelowAverageAge439* (boundary - region->getLowerAgeBound())440/ (region->getAllocationAge() - region->getLowerAgeBound()));441442liveBytesAboveBoundary -= liveBytesBelowBoundary;443444}445446} else {447if (region->getUpperAgeBound() > boundary) {448/* at least a fraction of the region is above boundary */449450/* first calculated the fraction of objects above average age */451UDATA liveBytesAboveAverageAge = (UDATA)(region->_projectedLiveBytesPreviousPGC452* (region->getAllocationAge() - region->getLowerAgeBound())453/ (region->getUpperAgeBound() - region->getLowerAgeBound()));454455/* now, find the fraction of above boundary */456liveBytesAboveBoundary = (UDATA)(liveBytesAboveAverageAge457* (region->getUpperAgeBound() - boundary)458/ (region->getUpperAgeBound() - region->getAllocationAge()));459}460461}462463liveBytesAboveBoundary = (UDATA)(nonEdenSpanExpandRatio * liveBytesAboveBoundary);464persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSetForNonEdenFraction += liveBytesAboveBoundary;465persistentStats[compactGroup]._projectedLiveBytesAfterPreviousPGCInCollectedSet += liveBytesAboveBoundary;466}467}468469470void471MM_CompactGroupPersistentStats::updateStatsBeforeCopyForward(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)472{473MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);474MM_HeapRegionManager *regionManager = extensions->heapRegionManager;475UDATA regionSize = regionManager->getRegionSize();476GC_HeapRegionIteratorVLHGC regionIterator(regionManager);477MM_HeapRegionDescriptorVLHGC *region = NULL;478479while(NULL != (region = regionIterator.nextRegion())) {480if (region->containsObjects()) {481UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);482483if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {484UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();485Assert_MM_true(completeFreeMemory <= regionSize);486UDATA measuredLiveBytes = regionSize - completeFreeMemory;487UDATA projectedLiveBytes = region->_projectedLiveBytes;488489persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;490persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;491if (region->_markData._shouldMark) {492calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);493}494}495}496}497}498499void500MM_CompactGroupPersistentStats::updateStatsAfterCopyForward(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)501{502UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);503for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {504if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {505UDATA liveBeforeCollect = persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet;506507if (liveBeforeCollect > 0) {508UDATA totalBytesBeforeCollect = persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup;509UDATA measuredNonParticipatingLiveBytes = (totalBytesBeforeCollect - liveBeforeCollect);510UDATA totalBytesAfterCollect = (persistentStats[compactGroup]._measuredBytesCopiedFromGroupDuringCopyForward + measuredNonParticipatingLiveBytes);511512Assert_MM_true(totalBytesBeforeCollect >= liveBeforeCollect);513514Assert_MM_true(totalBytesAfterCollect >= measuredNonParticipatingLiveBytes);515persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup = totalBytesAfterCollect;516persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet = totalBytesAfterCollect - measuredNonParticipatingLiveBytes;517}518}519}520521updateStatsAfterCollectionOperation(env, persistentStats);522}523524void525MM_CompactGroupPersistentStats::updateStatsBeforeSweep(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)526{527MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);528MM_HeapRegionManager *regionManager = extensions->heapRegionManager;529UDATA regionSize = regionManager->getRegionSize();530GC_HeapRegionIteratorVLHGC regionIterator(regionManager);531MM_HeapRegionDescriptorVLHGC *region = NULL;532533while(NULL != (region = regionIterator.nextRegion())) {534if (region->containsObjects()) {535UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);536537if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {538UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();539Assert_MM_true(completeFreeMemory <= regionSize);540UDATA measuredLiveBytes = regionSize - completeFreeMemory;541UDATA projectedLiveBytes = region->_projectedLiveBytes;542543persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;544persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;545if (!region->_sweepData._alreadySwept) {546calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);547}548}549}550}551}552553void554MM_CompactGroupPersistentStats::updateStatsAfterSweep(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)555{556MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);557MM_HeapRegionManager *regionManager = extensions->heapRegionManager;558UDATA regionSize = regionManager->getRegionSize();559GC_HeapRegionIteratorVLHGC regionIterator(regionManager, MM_HeapRegionDescriptor::ALL);560MM_HeapRegionDescriptorVLHGC *region = NULL;561562while(NULL != (region = regionIterator.nextRegion())) {563if (region->containsObjects()) {564UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);565566if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {567UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();568Assert_MM_true(completeFreeMemory <= regionSize);569UDATA measuredLiveBytes = regionSize - completeFreeMemory;570571persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup += measuredLiveBytes;572if (!region->_sweepData._alreadySwept) {573persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet += measuredLiveBytes;574}575}576}577}578updateStatsAfterCollectionOperation(env, persistentStats);579}580581void582MM_CompactGroupPersistentStats::updateStatsBeforeCompact(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)583{584MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);585MM_HeapRegionManager *regionManager = extensions->heapRegionManager;586UDATA regionSize = regionManager->getRegionSize();587GC_HeapRegionIteratorVLHGC regionIterator(regionManager);588MM_HeapRegionDescriptorVLHGC *region = NULL;589590while(NULL != (region = regionIterator.nextRegion())) {591if (region->containsObjects()) {592UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);593594if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {595UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();596Assert_MM_true(completeFreeMemory <= regionSize);597UDATA measuredLiveBytes = regionSize - completeFreeMemory;598UDATA projectedLiveBytes = region->_projectedLiveBytes;599600persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInGroup += measuredLiveBytes;601persistentStats[compactGroup]._projectedLiveBytesBeforeCollectInGroup += projectedLiveBytes;602if (region->_compactData._shouldCompact) {603calculateLiveBytesForRegion(env, persistentStats, compactGroup, region, measuredLiveBytes, projectedLiveBytes);604}605}606}607}608}609610void611MM_CompactGroupPersistentStats::updateStatsAfterCompact(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)612{613MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);614MM_HeapRegionManager *regionManager = extensions->heapRegionManager;615UDATA regionSize = regionManager->getRegionSize();616GC_HeapRegionIteratorVLHGC regionIterator(regionManager, MM_HeapRegionDescriptor::ALL);617MM_HeapRegionDescriptorVLHGC *region = NULL;618619while(NULL != (region = regionIterator.nextRegion())) {620if (region->containsObjects()) {621UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);622623if (!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {624UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();625Assert_MM_true(completeFreeMemory <= regionSize);626UDATA measuredLiveBytes = regionSize - completeFreeMemory;627628persistentStats[compactGroup]._measuredLiveBytesAfterCollectInGroup += measuredLiveBytes;629if (region->_compactData._shouldCompact) {630persistentStats[compactGroup]._measuredLiveBytesAfterCollectInCollectedSet += measuredLiveBytes;631}632}633}634}635updateStatsAfterCollectionOperation(env, persistentStats);636}637638void639MM_CompactGroupPersistentStats::initProjectedLiveBytes(MM_EnvironmentVLHGC *env)640{641MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);642GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);643MM_HeapRegionDescriptorVLHGC *region = NULL;644UDATA regionSize = extensions->heapRegionManager->getRegionSize();645646while (NULL != (region = regionIterator.nextRegion())) {647/* UDATA_MAX has a special meaning of 'uninitialized' */648if(region->containsObjects() && (UDATA_MAX == region->_projectedLiveBytes)) {649UDATA completeFreeMemory = region->getMemoryPool()->getFreeMemoryAndDarkMatterBytes();650Assert_MM_true(completeFreeMemory <= regionSize);651UDATA measuredLiveBytes = regionSize - completeFreeMemory;652region->_projectedLiveBytes = measuredLiveBytes;653}654}655}656657void658MM_CompactGroupPersistentStats::updateStatsAfterCollectionOperation(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)659{660bool compactGroupUpdated = false;661UDATA compactGroupCount = MM_CompactGroupManager::getCompactGroupMaxCount(env);662for (UDATA compactGroup = 0; compactGroup < compactGroupCount; compactGroup++) {663if (persistentStats[compactGroup]._measuredLiveBytesBeforeCollectInCollectedSet > 0) {664if(!persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle) {665persistentStats[compactGroup]._statsHaveBeenUpdatedThisCycle = true;666updateProjectedSurvivalRate(env, persistentStats, compactGroup);667compactGroupUpdated = true;668}669}670}671672if (compactGroupUpdated) {673deriveWeightedSurvivalRates(env, persistentStats);674}675}676677void678MM_CompactGroupPersistentStats::decayProjectedLiveBytesForRegions(MM_EnvironmentVLHGC *env)679{680MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);681GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager, MM_HeapRegionDescriptor::ALL);682MM_HeapRegionDescriptorVLHGC *region = NULL;683MM_CompactGroupPersistentStats * persistentStats = extensions->compactGroupPersistentStats;684685while (NULL != (region = regionIterator.nextRegion())) {686if(region->containsObjects()) {687/* before applying decay, take a snapshot of projectedLiveBytes used later for survivor rate calculation */688region->_projectedLiveBytesPreviousPGC = region->_projectedLiveBytes;689// TODO amicic: do we need to do on regions in eden (projectedLiveBytes is measuredLiveBytes)?690691I_64 allocatedSinceLastPGC = ((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->getAllocatedSinceLastPGC();692UDATA compactGroup = MM_CompactGroupManager::getCompactGroupNumber(env, region);693694I_64 currentAge = (I_64)region->getAllocationAge();695I_64 bytesRemaining = allocatedSinceLastPGC;696UDATA currentCompactGroup = compactGroup;697698while ((bytesRemaining > 0) && (currentAge > 0)) {699if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {700if ((currentAge <= (IDATA)persistentStats[currentCompactGroup - 1]._maxAllocationAge)) {701currentCompactGroup -= 1;702}703}704705double baseSurvivalRate = persistentStats[currentCompactGroup]._projectedInstantaneousSurvivalRatePerAgeUnit;706707U_64 minAllocationAgeForThisCompactGroup = 0;708709if (MM_CompactGroupManager::getRegionAgeFromGroup(env, currentCompactGroup) > 0) {710minAllocationAgeForThisCompactGroup = persistentStats[currentCompactGroup - 1]._maxAllocationAge;711}712713U_64 ageInThisGroup = OMR_MIN((U_64)bytesRemaining, (U_64)currentAge - minAllocationAgeForThisCompactGroup);714double ageUnitsInThisGroup = (double)ageInThisGroup / extensions->tarokAllocationAgeUnit;715double survivalRate = pow(baseSurvivalRate, ageUnitsInThisGroup);716717UDATA oldProjectedLiveBytes = region->_projectedLiveBytes;718region->_projectedLiveBytes = (UDATA) ((double)oldProjectedLiveBytes * survivalRate);719720Trc_MM_CompactGroupPersistentStats_decayProjectedLiveBytesForRegions(env->getLanguageVMThread(), extensions->heapRegionManager->mapDescriptorToRegionTableIndex(region),721(double)oldProjectedLiveBytes / (1024*1024), (double)region->_projectedLiveBytes / (1024*1024), compactGroup,722(double)bytesRemaining / (1024*1024), (double)currentAge / (1024*1024), survivalRate, baseSurvivalRate, ageUnitsInThisGroup, currentCompactGroup);723724bytesRemaining -= ageInThisGroup;725currentAge -= ageInThisGroup;726}727}728}729}730731void732MM_CompactGroupPersistentStats::updateStatsBeforeCollect(MM_EnvironmentVLHGC *env, MM_CompactGroupPersistentStats *persistentStats)733{734resetLiveBytesStats(env, persistentStats);735initProjectedLiveBytes(env);736decayProjectedLiveBytesForRegions(env);737}738739740