Added extra GC call before analyzing subgraph during freeze operation… (#4314)
This commit is contained in:
@@ -1679,7 +1679,7 @@ void garbageCollect(MemoryState* state, bool force) {
|
|||||||
GC_LOG("||| GC: collectCyclesDuration = %lld\n", cyclicGcEndTime - cyclicGcStartTime);
|
GC_LOG("||| GC: collectCyclesDuration = %lld\n", cyclicGcEndTime - cyclicGcStartTime);
|
||||||
#endif
|
#endif
|
||||||
auto cyclicGcDuration = cyclicGcEndTime - cyclicGcStartTime;
|
auto cyclicGcDuration = cyclicGcEndTime - cyclicGcStartTime;
|
||||||
if (state->gcErgonomics && cyclicGcDuration > kGcCollectCyclesMinimumDuration &&
|
if (!force && state->gcErgonomics && cyclicGcDuration > kGcCollectCyclesMinimumDuration &&
|
||||||
double(cyclicGcDuration) / (cyclicGcStartTime - state->lastCyclicGcTimestamp + 1) > kGcCollectCyclesLoadRatio) {
|
double(cyclicGcDuration) / (cyclicGcStartTime - state->lastCyclicGcTimestamp + 1) > kGcCollectCyclesLoadRatio) {
|
||||||
increaseGcCollectCyclesThreshold(state);
|
increaseGcCollectCyclesThreshold(state);
|
||||||
GC_LOG("Adjusting GC collecting cycles threshold to %lld\n", state->gcCollectCyclesThreshold);
|
GC_LOG("Adjusting GC collecting cycles threshold to %lld\n", state->gcCollectCyclesThreshold);
|
||||||
@@ -1692,7 +1692,7 @@ void garbageCollect(MemoryState* state, bool force) {
|
|||||||
|
|
||||||
if (state->gcErgonomics) {
|
if (state->gcErgonomics) {
|
||||||
auto gcToComputeRatio = double(gcEndTime - gcStartTime) / (gcStartTime - state->lastGcTimestamp + 1);
|
auto gcToComputeRatio = double(gcEndTime - gcStartTime) / (gcStartTime - state->lastGcTimestamp + 1);
|
||||||
if (gcToComputeRatio > kGcToComputeRatioThreshold) {
|
if (!force && gcToComputeRatio > kGcToComputeRatioThreshold) {
|
||||||
increaseGcThreshold(state);
|
increaseGcThreshold(state);
|
||||||
GC_LOG("Adjusting GC threshold to %d\n", state->gcThreshold);
|
GC_LOG("Adjusting GC threshold to %d\n", state->gcThreshold);
|
||||||
}
|
}
|
||||||
@@ -1997,6 +1997,16 @@ inline void checkIfGcNeeded(MemoryState* state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void checkIfForceCyclicGcNeeded(MemoryState* state) {
|
||||||
|
if (state != nullptr && state->toFree != nullptr && state->toFree->size() > kMaxToFreeSizeThreshold) {
|
||||||
|
// To avoid GC trashing check that at least 10ms passed since last GC.
|
||||||
|
if (konan::getTimeMicros() - state->lastGcTimestamp > 10 * 1000) {
|
||||||
|
GC_LOG("Calling GC from checkIfForceCyclicGcNeeded: %d\n", state->toFree->size())
|
||||||
|
garbageCollect(state, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool Strict>
|
template <bool Strict>
|
||||||
OBJ_GETTER(allocInstance, const TypeInfo* type_info) {
|
OBJ_GETTER(allocInstance, const TypeInfo* type_info) {
|
||||||
RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object");
|
RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object");
|
||||||
@@ -2400,6 +2410,9 @@ bool clearSubgraphReferences(ObjHeader* root, bool checked) {
|
|||||||
// TODO: assert for that?
|
// TODO: assert for that?
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Free cyclic garbage to decrease number of analyzed objects.
|
||||||
|
checkIfForceCyclicGcNeeded(state);
|
||||||
|
|
||||||
ContainerHeaderSet visited;
|
ContainerHeaderSet visited;
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
hasExternalRefs(container, &visited);
|
hasExternalRefs(container, &visited);
|
||||||
@@ -2601,6 +2614,12 @@ void freezeSubgraph(ObjHeader* root) {
|
|||||||
|
|
||||||
MEMORY_LOG("Freeze subgraph of %p\n", root)
|
MEMORY_LOG("Freeze subgraph of %p\n", root)
|
||||||
|
|
||||||
|
#if USE_GC
|
||||||
|
auto state = memoryState;
|
||||||
|
// Free cyclic garbage to decrease number of analyzed objects.
|
||||||
|
checkIfForceCyclicGcNeeded(state);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Do DFS cycle detection.
|
// Do DFS cycle detection.
|
||||||
bool hasCycles = false;
|
bool hasCycles = false;
|
||||||
KRef firstBlocker = root->has_meta_object() && ((root->meta_object()->flags_ & MF_NEVER_FROZEN) != 0) ?
|
KRef firstBlocker = root->has_meta_object() && ((root->meta_object()->flags_ & MF_NEVER_FROZEN) != 0) ?
|
||||||
@@ -2624,7 +2643,6 @@ void freezeSubgraph(ObjHeader* root) {
|
|||||||
// Now remove frozen objects from the toFree list.
|
// Now remove frozen objects from the toFree list.
|
||||||
// TODO: optimize it by keeping ignored (i.e. freshly frozen) objects in the set,
|
// TODO: optimize it by keeping ignored (i.e. freshly frozen) objects in the set,
|
||||||
// and use it when analyzing toFree during collection.
|
// and use it when analyzing toFree during collection.
|
||||||
auto state = memoryState;
|
|
||||||
for (auto& container : *(state->toFree)) {
|
for (auto& container : *(state->toFree)) {
|
||||||
if (!isMarkedAsRemoved(container) && container->frozen()) {
|
if (!isMarkedAsRemoved(container) && container->frozen()) {
|
||||||
RuntimeAssert(newlyFrozen.count(container) != 0, "Must be newly frozen");
|
RuntimeAssert(newlyFrozen.count(container) != 0, "Must be newly frozen");
|
||||||
|
|||||||
Reference in New Issue
Block a user