Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime recalculate GMP kickoff headroom #2119

Merged
merged 1 commit into from
Jul 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions runtime/gc_modron_startup/mminit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,12 +760,6 @@ gcInitializeCalculatedValues(J9JavaVM *javaVM, IDATA* memoryParameters)
extensions->tarokRememberedSetCardListMaxSize = 8 * extensions->tarokRememberedSetCardListSize;
}

if (0 == extensions->tarokKickoffHeadroomRegionCount) {
/* If kickoff headroom is not set, the default is (arbitrarily chosen to be) 1% of heap */
UDATA regionCount = extensions->memoryMax / extensions->regionSize;
extensions->tarokKickoffHeadroomRegionCount = regionCount / 100;
}

#endif /* defined (J9VM_GC_VLHGC) */

/* Number of GC threads must be initialized at this point */
Expand Down
18 changes: 16 additions & 2 deletions runtime/gc_modron_startup/mmparseXXgc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,25 @@ gcParseXXgcArguments(J9JavaVM *vm, char *optArg)
continue;
}

if (try_scan(&scan_start, "tarokKickoffHeadroomRegionCount=")) {
if(!scan_udata_memory_size_helper(vm, &scan_start, &(extensions->tarokKickoffHeadroomRegionCount), "tarokKickoffHeadroomRegionCount=")) {
if (try_scan(&scan_start, "tarokKickoffHeadroomRegionRate=")) {
if(!scan_u32_helper(vm, &scan_start, &(extensions->tarokKickoffHeadroomRegionRate), "tarokKickoffHeadroomRegionRate=")) {
returnValue = JNI_EINVAL;
break;
}
if (50 < extensions->tarokKickoffHeadroomRegionRate) {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_INTEGER_OUT_OF_RANGE, "tarokKickoffHeadroomRegionRate=", (UDATA)0, (UDATA)50);
returnValue = JNI_EINVAL;
break;
}
continue;
}

if (try_scan(&scan_start, "tarokKickoffHeadroomInBytes=")) {
if(!scan_udata_memory_size_helper(vm, &scan_start, &(extensions->tarokKickoffHeadroomInBytes), "tarokKickoffHeadroomInBytes=")) {
returnValue = JNI_EINVAL;
break;
}
extensions->tarokForceKickoffHeadroomInBytes = true;
continue;
}

Expand Down
3 changes: 3 additions & 0 deletions runtime/gc_vlhgc/IncrementalGenerationalGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,9 @@ MM_IncrementalGenerationalGC::initializeTaxationThreshold(MM_EnvironmentVLHGC *e

/* we need to calculate the taxation threshold after the initial heap inflation, which happens before collectorStartup */
_taxationThreshold = _schedulingDelegate.getInitialTaxationThreshold(env);
/* initialize GMP Kickoff Headroom Region Count */
_schedulingDelegate.initializeKickoffHeadroom(env);


UDATA minimumKickOff = extensions->regionSize * 2;
if (_taxationThreshold < minimumKickOff) {
Expand Down
55 changes: 47 additions & 8 deletions runtime/gc_vlhgc/SchedulingDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ MM_SchedulingDelegate::partialGarbageCollectCompleted(MM_EnvironmentVLHGC *env,
measureConsumptionForPartialGC(env, reclaimableRegions, defragmentReclaimableRegions);
calculateAutomaticGMPIntermission(env);
calculateEdenSize(env);

estimateMacroDefragmentationWork(env);

/* Calculate the time spent in the current Partial GC */
Expand Down Expand Up @@ -599,7 +598,7 @@ MM_SchedulingDelegate::estimatePartialGCsRemaining(MM_EnvironmentVLHGC *env) con

/* Calculate the number of regions that we need for copy forward destination */
double survivorRegions = _averageSurvivorSetRegionCount;
Trc_MM_SchedulingDelegate_estimatePartialGCsRemaining_survivorNeeds(env->getLanguageVMThread(), (UDATA)_averageSurvivorSetRegionCount, MM_GCExtensions::getExtensions(env)->tarokKickoffHeadroomRegionCount, (UDATA)survivorRegions);
Trc_MM_SchedulingDelegate_estimatePartialGCsRemaining_survivorNeeds(env->getLanguageVMThread(), (UDATA)_averageSurvivorSetRegionCount, MM_GCExtensions::getExtensions(env)->tarokKickoffHeadroomInBytes, (UDATA)survivorRegions);

double freeRegions = (double)((MM_GlobalAllocationManagerTarok *)_extensions->globalAllocationManager)->getFreeRegionCount();

Expand Down Expand Up @@ -712,6 +711,40 @@ MM_SchedulingDelegate::getDefragmentEmptinessThreshold(MM_EnvironmentVLHGC *env)

}

UDATA
MM_SchedulingDelegate::estimateTotalFreeMemory(MM_EnvironmentVLHGC *env, UDATA freeRegionMemory, UDATA defragmentedMemory, UDATA reservedFreeMemory)
{
UDATA estimatedFreeMemory = 0;

/* Adjust estimatedFreeMemory - we are only interested in area that shortfall can be fed from.
* Thus exclude reservedFreeMemory(Eden and Survivor size).
*/
estimatedFreeMemory = MM_Math::saturatingSubtract(defragmentedMemory + freeRegionMemory, reservedFreeMemory);

Trc_MM_SchedulingDelegate_estimateTotalFreeMemory(env->getLanguageVMThread(), estimatedFreeMemory, reservedFreeMemory, defragmentedMemory, freeRegionMemory);
return estimatedFreeMemory;
}

UDATA
MM_SchedulingDelegate::calculateKickoffHeadroom(MM_EnvironmentVLHGC *env, UDATA totalFreeMemory)
{
if (_extensions->tarokForceKickoffHeadroomInBytes) {
return _extensions->tarokKickoffHeadroomInBytes;
}
UDATA newHeadroom = totalFreeMemory * _extensions->tarokKickoffHeadroomRegionRate / 100;
Trc_MM_SchedulingDelegate_calculateKickoffHeadroom(env->getLanguageVMThread(), _extensions->tarokKickoffHeadroomInBytes, newHeadroom);
_extensions->tarokKickoffHeadroomInBytes = newHeadroom;
return newHeadroom;
}

UDATA
MM_SchedulingDelegate::initializeKickoffHeadroom(MM_EnvironmentVLHGC *env)
{
/* totoal free memory = total heap size - eden size */
UDATA totalFreeMemory = _regionManager->getTotalHeapSize() - getCurrentEdenSizeInBytes(env);
return calculateKickoffHeadroom(env, totalFreeMemory);
}

void
MM_SchedulingDelegate::calculatePGCCompactionRate(MM_EnvironmentVLHGC *env, UDATA edenSizeInBytes)
{
Expand Down Expand Up @@ -784,12 +817,18 @@ MM_SchedulingDelegate::calculatePGCCompactionRate(MM_EnvironmentVLHGC *env, UDAT
}
}

/* Adjust estimatedFreeMemory - we are only interested in area that shortfall can be fed from.
* Thus exclude Eden and Survivor size. Survivor space needs to accommodate for Nursery set, Dynamic collection set and Compaction set
/* Survivor space needs to accommodate for Nursery set, Dynamic collection set and Compaction set
*/
UDATA surivivorSize = (UDATA)(regionSize * (_averageSurvivorSetRegionCount + _extensions->tarokKickoffHeadroomRegionCount));
/* estimate totalFreeMemory for recalculating kickoffHeadroomRegionCount */
UDATA surivivorSize = (UDATA)(regionSize * _averageSurvivorSetRegionCount);
UDATA reservedFreeMemory = edenSizeInBytes + surivivorSize;
estimatedFreeMemory = MM_Math::saturatingSubtract(defragmentedMemory + freeRegionMemory, reservedFreeMemory);
estimatedFreeMemory = estimateTotalFreeMemory(env, freeRegionMemory, defragmentedMemory, reservedFreeMemory);
calculateKickoffHeadroom(env, estimatedFreeMemory);

/* estimate totalFreeMemory for recalculating PGCCompactionRate with tarokKickoffHeadroomInBytes */
reservedFreeMemory += _extensions->tarokKickoffHeadroomInBytes;
estimatedFreeMemory = estimateTotalFreeMemory(env, freeRegionMemory, defragmentedMemory, reservedFreeMemory);

double bytesDiscardedPerByteCopied = (_averageCopyForwardBytesCopied > 0.0) ? (_averageCopyForwardBytesDiscarded / _averageCopyForwardBytesCopied) : 0.0;
double estimatedFreeMemoryDiscarded = (double)totalLiveDataInCollectableRegions * bytesDiscardedPerByteCopied;
double recoverableFreeMemory = (double)estimatedFreeMemory - estimatedFreeMemoryDiscarded;
Expand Down Expand Up @@ -920,7 +959,7 @@ MM_SchedulingDelegate::calculateAutomaticGMPIntermission(MM_EnvironmentVLHGC *en
}
}

Trc_MM_SchedulingDelegate_calculateAutomaticGMPIntermission_Exit(env->getLanguageVMThread(), _remainingGMPIntermissionIntervals);
Trc_MM_SchedulingDelegate_calculateAutomaticGMPIntermission_1_Exit(env->getLanguageVMThread(), _remainingGMPIntermissionIntervals, _extensions->tarokKickoffHeadroomInBytes);
}

void
Expand Down Expand Up @@ -1063,7 +1102,7 @@ MM_SchedulingDelegate::calculateGlobalMarkIncrementHeadroom(MM_EnvironmentVLHGC
UDATA headroomIncrements = 0;

if (_regionConsumptionRate > 0.0) {
double headroomRegions = (double) _extensions->tarokKickoffHeadroomRegionCount;
double headroomRegions = (double) _extensions->tarokKickoffHeadroomInBytes / _regionManager->getRegionSize();
double headroomPartialGCs = headroomRegions / _regionConsumptionRate;
double headroomGlobalMarkIncrements = headroomPartialGCs * (double)_extensions->tarokPGCtoGMPDenominator / (double)_extensions->tarokPGCtoGMPNumerator;
headroomIncrements = (UDATA) ceil(headroomGlobalMarkIncrements);
Expand Down
17 changes: 17 additions & 0 deletions runtime/gc_vlhgc/SchedulingDelegate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,26 @@ class MM_SchedulingDelegate : public MM_BaseNonVirtual
*/
double calculateAverageCopyForwardRate(MM_EnvironmentVLHGC *env);

/**
* Estimate total free memory
* @param env[in] the master GC thread
* @oaram freeRegionMemory[in]
* @param defragmentedMemory[in]
* @oaram reservedFreeMemory[in]
* @return total free memory(bytes)
*/
UDATA estimateTotalFreeMemory(MM_EnvironmentVLHGC *env, UDATA freeRegionMemory, UDATA defragmentedMemory, UDATA reservedFreeMemory);

/**
* Calculate GMP Kickoff Headroom In Bytes
* the
*/
UDATA calculateKickoffHeadroom(MM_EnvironmentVLHGC *env, UDATA totalFreeMemory);

protected:

public:
UDATA initializeKickoffHeadroom(MM_EnvironmentVLHGC *env);

/**
* Calculate the allocation threshold for the first taxation period. This should be called
Expand Down