[K/N] Reuse mark queue ^KT-51436

Merge-request: KT-MR-5819
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-02-22 11:01:15 +00:00
committed by Space
parent 14dc20186d
commit 964edbaf91
7 changed files with 17 additions and 12 deletions
@@ -85,6 +85,7 @@ gc::ConcurrentMarkAndSweep::ConcurrentMarkAndSweep(
objectFactory_(objectFactory), objectFactory_(objectFactory),
gcScheduler_(gcScheduler), gcScheduler_(gcScheduler),
finalizerProcessor_(make_unique<FinalizerProcessor>([this](int64_t epoch) { state_.finalized(epoch); })) { finalizerProcessor_(make_unique<FinalizerProcessor>([this](int64_t epoch) { state_.finalized(epoch); })) {
graySet_.reserve(1000);
gcScheduler_.SetScheduleGC([this]() NO_INLINE { gcScheduler_.SetScheduleGC([this]() NO_INLINE {
RuntimeLogDebug({kTagGC}, "Scheduling GC by thread %d", konan::currentThreadId()); 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. // 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); state_.start(epoch);
RuntimeLogInfo( RuntimeLogInfo(
{kTagGC}, "Started GC epoch %" PRId64 ". Time since last GC %" PRIu64 " microseconds", epoch, timeStartUs - lastGCTimestampUs_); {kTagGC}, "Started GC epoch %" PRId64 ". Time since last GC %" PRIu64 " microseconds", epoch, timeStartUs - lastGCTimestampUs_);
auto graySet = collectRootSet(); collectRootSet(graySet_);
auto timeRootSetUs = konan::getTimeMicros(); auto timeRootSetUs = konan::getTimeMicros();
// Can be unsafe, because we've stopped the world. // Can be unsafe, because we've stopped the world.
auto objectsCountBefore = objectFactory_.GetSizeUnsafe(); auto objectsCountBefore = objectFactory_.GetSizeUnsafe();
RuntimeLogInfo( 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); timeRootSetUs - timeSuspendUs);
auto markStats = gc::Mark<MarkTraits>(std::move(graySet)); auto markStats = gc::Mark<MarkTraits>(graySet_);
auto timeMarkUs = konan::getTimeMicros(); 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); 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); scheduler.gcData().UpdateAliveSetBytes(markStats.aliveHeapSetBytes);
@@ -88,6 +88,8 @@ private:
GCStateHolder state_; GCStateHolder state_;
ScopedThread gcThread_; ScopedThread gcThread_;
KStdUniquePtr<FinalizerProcessor> finalizerProcessor_; KStdUniquePtr<FinalizerProcessor> finalizerProcessor_;
KStdVector<ObjHeader*> graySet_;
}; };
} // namespace gc } // namespace gc
@@ -13,8 +13,8 @@
using namespace kotlin; using namespace kotlin;
KStdVector<ObjHeader*> kotlin::gc::collectRootSet() { void kotlin::gc::collectRootSet(KStdVector<ObjHeader*>& graySet) {
KStdVector<ObjHeader*> graySet; graySet.clear();
for (auto& thread : mm::GlobalData::Instance().threadRegistry().LockForIter()) { for (auto& thread : mm::GlobalData::Instance().threadRegistry().LockForIter()) {
// TODO: Maybe it's more efficient to do by the suspending thread? // TODO: Maybe it's more efficient to do by the suspending thread?
thread.Publish(); thread.Publish();
@@ -53,5 +53,4 @@ KStdVector<ObjHeader*> kotlin::gc::collectRootSet() {
} }
} }
RuntimeLogDebug({kTagGC}, "Collected global root set global=%zu stableRef=%zu", global, stableRef); RuntimeLogDebug({kTagGC}, "Collected global root set global=%zu stableRef=%zu", global, stableRef);
return graySet;
} }
@@ -28,7 +28,7 @@ struct MarkStats {
// TODO: Because of `graySet` this implementation may allocate heap memory during GC. // TODO: Because of `graySet` this implementation may allocate heap memory during GC.
template <typename Traits> template <typename Traits>
MarkStats Mark(KStdVector<ObjHeader*> graySet) noexcept { MarkStats Mark(KStdVector<ObjHeader*>& graySet) noexcept {
MarkStats stats; MarkStats stats;
while (!graySet.empty()) { while (!graySet.empty()) {
ObjHeader* top = graySet.back(); ObjHeader* top = graySet.back();
@@ -111,7 +111,7 @@ typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFact
return Sweep<Traits>(iter); return Sweep<Traits>(iter);
} }
KStdVector<ObjHeader*> collectRootSet(); void collectRootSet(KStdVector<ObjHeader*>& graySet);
} // namespace gc } // namespace gc
} // namespace kotlin } // namespace kotlin
@@ -147,7 +147,7 @@ public:
gc::MarkStats Mark(std::initializer_list<std::reference_wrapper<BaseObject>> graySet) { gc::MarkStats Mark(std::initializer_list<std::reference_wrapper<BaseObject>> graySet) {
KStdVector<ObjHeader*> objects; KStdVector<ObjHeader*> objects;
for (auto& object : graySet) objects.push_back(object.get().GetObjHeader()); for (auto& object : graySet) objects.push_back(object.get().GetObjHeader());
return gc::Mark<ScopedMarkTraits>(std::move(objects)); return gc::Mark<ScopedMarkTraits>(objects);
} }
private: private:
@@ -104,6 +104,7 @@ NO_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointSlowPath(Safepoi
gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep( gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep(
mm::ObjectFactory<SameThreadMarkAndSweep>& objectFactory, GCScheduler& gcScheduler) noexcept : mm::ObjectFactory<SameThreadMarkAndSweep>& objectFactory, GCScheduler& gcScheduler) noexcept :
objectFactory_(objectFactory), gcScheduler_(gcScheduler) { objectFactory_(objectFactory), gcScheduler_(gcScheduler) {
graySet_.reserve(1000);
gcScheduler_.SetScheduleGC([]() { gcScheduler_.SetScheduleGC([]() {
// TODO: CMS is also responsible for avoiding scheduling while GC hasn't started running. // 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. // Investigate, if it's possible to move this logic into the scheduler.
@@ -142,15 +143,15 @@ bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept {
RuntimeLogInfo( RuntimeLogInfo(
{kTagGC}, "Started GC epoch %zu. Time since last GC %" PRIu64 " microseconds", epoch_, timeStartUs - lastGCTimestampUs_); {kTagGC}, "Started GC epoch %zu. Time since last GC %" PRIu64 " microseconds", epoch_, timeStartUs - lastGCTimestampUs_);
auto graySet = collectRootSet(); collectRootSet(graySet_);
auto timeRootSetUs = konan::getTimeMicros(); auto timeRootSetUs = konan::getTimeMicros();
// Can be unsafe, because we've stopped the world. // Can be unsafe, because we've stopped the world.
auto objectsCountBefore = objectFactory_.GetSizeUnsafe(); auto objectsCountBefore = objectFactory_.GetSizeUnsafe();
RuntimeLogInfo( 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); timeRootSetUs - timeSuspendUs);
auto markStats = gc::Mark<MarkTraits>(std::move(graySet)); auto markStats = gc::Mark<MarkTraits>(graySet_);
auto timeMarkUs = konan::getTimeMicros(); 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); 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); scheduler.gcData().UpdateAliveSetBytes(markStats.aliveHeapSetBytes);
@@ -85,6 +85,8 @@ private:
mm::ObjectFactory<SameThreadMarkAndSweep>& objectFactory_; mm::ObjectFactory<SameThreadMarkAndSweep>& objectFactory_;
GCScheduler& gcScheduler_; GCScheduler& gcScheduler_;
KStdVector<ObjHeader*> graySet_;
}; };
namespace internal { namespace internal {