Skip to content

Commit

Permalink
Heap size startup hints
Browse files Browse the repository at this point in the history
Initial contribution of feature where on PHASE_NOT_STARTUP phase change
GC will store current heap sizes (optionally, averaged with already
existing stored values) into Shared Cache. During early startup GC will
use these hints to expand heap beyond default or even explicitly
specified sizes.

This should help large workloads to avoid early GCs while heap is
aggressively expanding, which in turn may help with startup times.

In this contribution, Standard group of GC policies are covered, with
Balanced GC following at a later point.

For Flat heap configurations (optthruput/optavgpause) only the total
heap size is maintained/expanded, while for generational configuration,
Tenure and Nursery are separately maintained/expanded.

The feature is disabled by default, but can be enabled by specifying
value [1-100] to -XXgc:heapSizeStatupHintWeightNewValue= command line
option. Reasonable value is 80, which should typically take about 5
restarts for hints to converge to stable values. Value 0 (currently
defaults) means that new values are never accounted for, which means
that values are always 0, which effectively means that feature is
disabled. Value 100 would mean that only use the hints from the most
recent run, hence no historical averaging.

Another tuning options is -XXgc:heapSizeStatupHintConservativeFactor=
Default value is 70. It means that conservatively only 70% of the hint
values are taken.

An example of verbose GC stanzas reporting the expand just after
initialized stanza is complete, before even first GC:

```
.....
</initialized>

<heap-resize id="2" type="expand" space="nursery" amount="1461583872"
count="1" timems="1.738" reason="hint from previous runs"
timestamp="2019-01-03T12:59:54.909" />
<heap-resize id="3" type="expand" space="tenure" amount="200212480"
count="1" timems="0.930" reason="hint from previous runs"
timestamp="2019-01-03T12:59:54.910" />
```

Signed-off-by: Aleksandar Micic <amicic@ca.ibm.com>
  • Loading branch information
amicic committed Jan 8, 2019
1 parent 1e7ab9b commit f626d6c
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 8 deletions.
4 changes: 3 additions & 1 deletion runtime/gc/dllinit.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2017 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -91,6 +91,8 @@ J9VMDllMain(J9JavaVM* vm, IDATA stage, void* reserved)
break;

case ABOUT_TO_BOOTSTRAP :
/* Expand heap based on hints stored by previous runs into Shared Cache */
gcExpandHeapOnStartup(vm);
case JCL_INITIALIZED :
case LIBRARIES_ONUNLOAD :
break;
Expand Down
3 changes: 2 additions & 1 deletion runtime/gc/gctable.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -53,6 +53,7 @@ J9MemoryManagerFunctions MemoryManagerFunctions = {
j9gc_get_private_hook_interface,
gcStartupHeapManagement,
gcShutdownHeapManagement,
j9gc_jvmPhaseChange,
initializeMutatorModelJava,
cleanupMutatorModelJava,
#if defined(J9VM_GC_FINALIZATION)
Expand Down
3 changes: 2 additions & 1 deletion runtime/gc_base/gc_internal.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -101,6 +101,7 @@ extern J9_CFUNC void j9gc_objaccess_copyObjectFields(J9VMThread *vmThread, J9Cla
extern J9_CFUNC j9object_t j9gc_objaccess_asConstantPoolObject(J9VMThread *vmThread, j9object_t toConvert, UDATA allocationFlags);
extern J9_CFUNC jvmtiIterationControl j9mm_iterate_heaps(J9JavaVM *vm, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl(*func)(J9JavaVM *vm, struct J9MM_IterateHeapDescriptor *heapDesc, void *userData), void *userData);
extern J9_CFUNC int gcStartupHeapManagement(J9JavaVM * vm);
extern J9_CFUNC void j9gc_jvmPhaseChange(J9VMThread *currentThread, UDATA phase);
extern J9_CFUNC void j9gc_ext_reachable_from_object_do(J9VMThread *vmThread, j9object_t objectPtr, jvmtiIterationControl(*func)(j9object_t *slotPtr, j9object_t sourcePtr, void *userData, IDATA type, IDATA index, IDATA wasReportedBefore), void *userData, UDATA walkFlags);
extern J9_CFUNC UDATA moveObjectToMemorySpace(J9VMThread *vmThread, void *destinationMemorySpace, j9object_t objectPtr);
/* TODO: The signature of allocateMemoryForSublistFragment temporarily uses void* instead of OMR_VMThread* since the latter is a class */
Expand Down
104 changes: 103 additions & 1 deletion runtime/gc_modron_startup/mminit.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -597,6 +597,108 @@ gcStartupHeapManagement(J9JavaVM *javaVM)
return result;
}

void j9gc_jvmPhaseChange(J9VMThread *currentThread, UDATA phase)
{
J9JavaVM *vm = currentThread->javaVM;
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
MM_EnvironmentBase env(currentThread->omrVMThread);
if (J9VM_PHASE_NOT_STARTUP == phase) {

if (NULL != vm->sharedClassConfig) {
if (extensions->isStandardGC()) {
/* read old values from SC */
uintptr_t hintDefaultOld = 0;
uintptr_t hintTenureOld = 0;
vm->sharedClassConfig->findGCHints(currentThread, &hintDefaultOld, &hintTenureOld);
/* Nothing to do if read fails, we'll just assume the old values are 0 */

/* Get the current heap size values.
* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).
* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.
* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.
*/
MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();
MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();

/* Default MSS is either OLD or NEW at a time (flat or generational), but we can safely ask for both. We cannot just use plain
* getActiveMemorySize() without arguments since it would return just Allocate size for Nursery, but we need total Nursery size.
*/
uintptr_t hintDefault = defaultMemorySubSpace->getActiveMemorySize(MEMORY_TYPE_OLD | MEMORY_TYPE_NEW);
uintptr_t hintTenure = 0;

/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).
* So the simplest is always fetch Default, regardless if's generational haep configuration or not.
* We fetch Tenure only if only not equal to Default (which implies it's generational) */
if (defaultMemorySubSpace != tenureMemorySubspace) {
hintTenure = tenureMemorySubspace->getActiveMemorySize();
}

/* Gradually learn, by averaging new values with old values - it may take a few restarts before hint converge to stable values */
hintDefault = (uintptr_t)MM_Math::weightedAverage(hintDefaultOld, hintDefault, (1.0 - extensions->heapSizeStatupHintWeightNewValue));
hintTenure = (uintptr_t)MM_Math::weightedAverage(hintTenureOld, hintTenure, (1.0 - extensions->heapSizeStatupHintWeightNewValue));

vm->sharedClassConfig->storeGCHints(currentThread, hintDefault, hintTenure, true);
/* Nothing to do if store fails, storeGCHints already issues a trace point */
}
}
}
}


void
gcExpandHeapOnStartup(J9JavaVM *javaVM)
{
J9SharedClassConfig *sharedClassConfig = javaVM->sharedClassConfig;
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
J9VMThread *currentThread = javaVM->internalVMFunctions->currentVMThread(javaVM);
MM_EnvironmentBase env(currentThread->omrVMThread);

if (NULL != sharedClassConfig) {
if (extensions->isStandardGC()) {
uintptr_t hintDefault = 0;
uintptr_t hintTenure = 0;

if (0 == sharedClassConfig->findGCHints(currentThread, &hintDefault, &hintTenure)) {

/* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).
* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.
* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.
*/
MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();
MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();


/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).
* So the simplest is always deal with Default, regardless if's generational heap configuration or not.
* We deal with Tenure only if only not equal to Default (which implies it's generational)
* We are a bit conservative and aim for slightly lower values that historically recorded by hints.
*/
uintptr_t hintDefaultAdjusted = (uintptr_t)(hintDefault * extensions->heapSizeStatupHintConservativeFactor);
uintptr_t defaultCurrent = defaultMemorySubSpace->getActiveMemorySize(MEMORY_TYPE_OLD | MEMORY_TYPE_NEW);
if (hintDefaultAdjusted > defaultCurrent) {
extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);
defaultMemorySubSpace->expand(&env, hintDefaultAdjusted - defaultCurrent);
}


if (defaultMemorySubSpace != tenureMemorySubspace) {
uintptr_t hintTenureAdjusted = (uintptr_t)(hintTenure * extensions->heapSizeStatupHintConservativeFactor);
uintptr_t tenureCurrent = tenureMemorySubspace->getActiveMemorySize();

if (hintTenureAdjusted > tenureCurrent) {
extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);
tenureMemorySubspace->expand(&env, hintTenureAdjusted - tenureCurrent);
}
}

}
/* Nothing to do if findGCHints failed. It already issues a trace point - no need to duplicate it here */
}
/* todo: Balanced GC */
}
}


/**
* Cleanup Finalizer and Heap components
*/
Expand Down
5 changes: 4 additions & 1 deletion runtime/gc_modron_startup/mminit.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2017 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -49,6 +49,9 @@ void gcCleanupHeapStructures(J9JavaVM* vm);

jint triggerGCInitialized(J9VMThread* vmThread);

void gcExpandHeapOnStartup(J9JavaVM *javaVM);


#ifdef __cplusplus
} /* extern "C" { */
#endif
Expand Down
30 changes: 29 additions & 1 deletion runtime/gc_modron_startup/mmparseXXgc.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -937,6 +937,34 @@ gcParseXXgcArguments(J9JavaVM *vm, char *optArg)
continue;
}

if (try_scan(&scan_start, "heapSizeStatupHintConservativeFactor=")) {
UDATA percentage = 0;
if(!scan_udata_helper(vm, &scan_start, &percentage, "heapSizeStatupHintConservativeFactor=")) {
returnValue = JNI_EINVAL;
break;
}
if(percentage > 100) {
returnValue = JNI_EINVAL;
break;
}
extensions->heapSizeStatupHintConservativeFactor = ((float)percentage) / 100.0;
continue ;
}

if (try_scan(&scan_start, "heapSizeStatupHintWeightNewValue=")) {
UDATA percentage = 0;
if(!scan_udata_helper(vm, &scan_start, &percentage, "heapSizeStatupHintWeightNewValue=")) {
returnValue = JNI_EINVAL;
break;
}
if(percentage > 100) {
returnValue = JNI_EINVAL;
break;
}
extensions->heapSizeStatupHintWeightNewValue = ((float)percentage) / 100.0;
continue ;
}

#if defined (J9VM_GC_VLHGC)
if (try_scan(&scan_start, "fvtest_tarokSimulateNUMA=")) {
UDATA simulatedNodeCount = 0;
Expand Down
3 changes: 2 additions & 1 deletion runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -4298,6 +4298,7 @@ typedef struct J9MemoryManagerFunctions {

int ( *gcStartupHeapManagement)(struct J9JavaVM * vm) ;
void ( *gcShutdownHeapManagement)(struct J9JavaVM * vm) ;
void ( *jvmPhaseChange)(struct J9VMThread *currentThread, UDATA phase);
IDATA ( *initializeMutatorModelJava)(struct J9VMThread* vmThread) ;
void ( *cleanupMutatorModelJava)(struct J9VMThread* vmThread) ;
#if defined(J9VM_GC_FINALIZATION)
Expand Down
5 changes: 4 additions & 1 deletion runtime/vm/vmphases.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2013, 2014 IBM Corp. and others
* Copyright (c) 2013, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -63,6 +63,9 @@ void jvmPhaseChange(J9JavaVM* vm, UDATA phase) {
((J9UtServerInterface *)((UtInterface *)tempRasGbl->utIntf)->server)->StartupComplete(currentThread);
}
}
if (NULL != vm->memoryManagerFunctions) {
vm->memoryManagerFunctions->jvmPhaseChange(currentThread, phase);
}
if (NULL != vm->sharedClassConfig) {
vm->sharedClassConfig->jvmPhaseChange(currentThread, phase);
}
Expand Down

0 comments on commit f626d6c

Please sign in to comment.