From 964edbaf91dddf216baf996de7f93b688d64095f Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Tue, 22 Feb 2022 11:01:15 +0000 Subject: [PATCH] [K/N] Reuse mark queue ^KT-51436 Merge-request: KT-MR-5819 Merged-by: Alexander Shabalin --- .../runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp | 7 ++++--- .../runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp | 2 ++ .../runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp | 5 ++--- .../runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp | 4 ++-- .../src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp | 2 +- .../runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp | 7 ++++--- .../runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.hpp | 2 ++ 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp index a9d9d0ce562..b77b4016f95 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp @@ -85,6 +85,7 @@ gc::ConcurrentMarkAndSweep::ConcurrentMarkAndSweep( objectFactory_(objectFactory), gcScheduler_(gcScheduler), finalizerProcessor_(make_unique([this](int64_t epoch) { state_.finalized(epoch); })) { + graySet_.reserve(1000); gcScheduler_.SetScheduleGC([this]() NO_INLINE { RuntimeLogDebug({kTagGC}, "Scheduling GC by thread %d", konan::currentThreadId()); // This call acquires a lock, so we need to ensure that we're in the safe state. @@ -142,15 +143,15 @@ bool gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept { state_.start(epoch); RuntimeLogInfo( {kTagGC}, "Started GC epoch %" PRId64 ". Time since last GC %" PRIu64 " microseconds", epoch, timeStartUs - lastGCTimestampUs_); - auto graySet = collectRootSet(); + collectRootSet(graySet_); auto timeRootSetUs = konan::getTimeMicros(); // Can be unsafe, because we've stopped the world. auto objectsCountBefore = objectFactory_.GetSizeUnsafe(); RuntimeLogInfo( - {kTagGC}, "Collected root set of size %zu in %" PRIu64 " microseconds", graySet.size(), + {kTagGC}, "Collected root set of size %zu in %" PRIu64 " microseconds", graySet_.size(), timeRootSetUs - timeSuspendUs); - auto markStats = gc::Mark(std::move(graySet)); + auto markStats = gc::Mark(graySet_); auto timeMarkUs = konan::getTimeMicros(); RuntimeLogDebug({kTagGC}, "Marked %zu objects in %" PRIu64 " microseconds. Processed %zu duplicate entries in the gray set", markStats.aliveHeapSet, timeMarkUs - timeRootSetUs, markStats.duplicateEntries); scheduler.gcData().UpdateAliveSetBytes(markStats.aliveHeapSetBytes); diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp index 12c88551ef2..e4c0960fdc8 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.hpp @@ -88,6 +88,8 @@ private: GCStateHolder state_; ScopedThread gcThread_; KStdUniquePtr finalizerProcessor_; + + KStdVector graySet_; }; } // namespace gc diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp index ddde4ed8ab7..9d167e2bd98 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp @@ -13,8 +13,8 @@ using namespace kotlin; -KStdVector kotlin::gc::collectRootSet() { - KStdVector graySet; +void kotlin::gc::collectRootSet(KStdVector& graySet) { + graySet.clear(); for (auto& thread : mm::GlobalData::Instance().threadRegistry().LockForIter()) { // TODO: Maybe it's more efficient to do by the suspending thread? thread.Publish(); @@ -53,5 +53,4 @@ KStdVector kotlin::gc::collectRootSet() { } } RuntimeLogDebug({kTagGC}, "Collected global root set global=%zu stableRef=%zu", global, stableRef); - return graySet; } diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp index dbb67c3b365..d5a3de6e661 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp @@ -28,7 +28,7 @@ struct MarkStats { // TODO: Because of `graySet` this implementation may allocate heap memory during GC. template -MarkStats Mark(KStdVector graySet) noexcept { +MarkStats Mark(KStdVector& graySet) noexcept { MarkStats stats; while (!graySet.empty()) { ObjHeader* top = graySet.back(); @@ -111,7 +111,7 @@ typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFact return Sweep(iter); } -KStdVector collectRootSet(); +void collectRootSet(KStdVector& graySet); } // namespace gc } // namespace kotlin diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp index 82f28f98bf5..e1b3f92fd7e 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp @@ -147,7 +147,7 @@ public: gc::MarkStats Mark(std::initializer_list> graySet) { KStdVector objects; for (auto& object : graySet) objects.push_back(object.get().GetObjHeader()); - return gc::Mark(std::move(objects)); + return gc::Mark(objects); } private: diff --git a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp index 9a4963f440f..2cf88ea7ea9 100644 --- a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp @@ -104,6 +104,7 @@ NO_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointSlowPath(Safepoi gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep( mm::ObjectFactory& objectFactory, GCScheduler& gcScheduler) noexcept : objectFactory_(objectFactory), gcScheduler_(gcScheduler) { + graySet_.reserve(1000); gcScheduler_.SetScheduleGC([]() { // TODO: CMS is also responsible for avoiding scheduling while GC hasn't started running. // Investigate, if it's possible to move this logic into the scheduler. @@ -142,15 +143,15 @@ bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept { RuntimeLogInfo( {kTagGC}, "Started GC epoch %zu. Time since last GC %" PRIu64 " microseconds", epoch_, timeStartUs - lastGCTimestampUs_); - auto graySet = collectRootSet(); + collectRootSet(graySet_); auto timeRootSetUs = konan::getTimeMicros(); // Can be unsafe, because we've stopped the world. auto objectsCountBefore = objectFactory_.GetSizeUnsafe(); RuntimeLogInfo( - {kTagGC}, "Collected root set of size %zu in %" PRIu64 " microseconds", graySet.size(), + {kTagGC}, "Collected root set of size %zu in %" PRIu64 " microseconds", graySet_.size(), timeRootSetUs - timeSuspendUs); - auto markStats = gc::Mark(std::move(graySet)); + auto markStats = gc::Mark(graySet_); auto timeMarkUs = konan::getTimeMicros(); RuntimeLogDebug({kTagGC}, "Marked %zu objects in %" PRIu64 " microseconds. Processed %zu duplicate entries in the gray set", markStats.aliveHeapSet, timeMarkUs - timeRootSetUs, markStats.duplicateEntries); scheduler.gcData().UpdateAliveSetBytes(markStats.aliveHeapSetBytes); diff --git a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.hpp b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.hpp index 6a24871dc18..172b643f766 100644 --- a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.hpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.hpp @@ -85,6 +85,8 @@ private: mm::ObjectFactory& objectFactory_; GCScheduler& gcScheduler_; + + KStdVector graySet_; }; namespace internal {