[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),
gcScheduler_(gcScheduler),
finalizerProcessor_(make_unique<FinalizerProcessor>([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<MarkTraits>(std::move(graySet));
auto markStats = gc::Mark<MarkTraits>(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);
@@ -88,6 +88,8 @@ private:
GCStateHolder state_;
ScopedThread gcThread_;
KStdUniquePtr<FinalizerProcessor> finalizerProcessor_;
KStdVector<ObjHeader*> graySet_;
};
} // namespace gc
@@ -13,8 +13,8 @@
using namespace kotlin;
KStdVector<ObjHeader*> kotlin::gc::collectRootSet() {
KStdVector<ObjHeader*> graySet;
void kotlin::gc::collectRootSet(KStdVector<ObjHeader*>& 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<ObjHeader*> kotlin::gc::collectRootSet() {
}
}
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.
template <typename Traits>
MarkStats Mark(KStdVector<ObjHeader*> graySet) noexcept {
MarkStats Mark(KStdVector<ObjHeader*>& 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<Traits>(iter);
}
KStdVector<ObjHeader*> collectRootSet();
void collectRootSet(KStdVector<ObjHeader*>& graySet);
} // namespace gc
} // namespace kotlin
@@ -147,7 +147,7 @@ public:
gc::MarkStats Mark(std::initializer_list<std::reference_wrapper<BaseObject>> graySet) {
KStdVector<ObjHeader*> objects;
for (auto& object : graySet) objects.push_back(object.get().GetObjHeader());
return gc::Mark<ScopedMarkTraits>(std::move(objects));
return gc::Mark<ScopedMarkTraits>(objects);
}
private:
@@ -104,6 +104,7 @@ NO_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointSlowPath(Safepoi
gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep(
mm::ObjectFactory<SameThreadMarkAndSweep>& 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<MarkTraits>(std::move(graySet));
auto markStats = gc::Mark<MarkTraits>(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);
@@ -85,6 +85,8 @@ private:
mm::ObjectFactory<SameThreadMarkAndSweep>& objectFactory_;
GCScheduler& gcScheduler_;
KStdVector<ObjHeader*> graySet_;
};
namespace internal {