1 /** 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef PANDA_RUNTIME_MEM_GC_G1_G1_EVACUATE_REGIONS_TASK_H 16 #define PANDA_RUNTIME_MEM_GC_G1_G1_EVACUATE_REGIONS_TASK_H 17 18 #include "runtime/mem/gc/workers/gc_workers_tasks.h" 19 #include "runtime/mem/gc/g1/g1-evacuate-regions-worker-state-inl.h" 20 21 namespace ark::mem { 22 23 class GcThreadScope { 24 public: GcThreadScope(Thread * gcThread)25 explicit GcThreadScope(Thread *gcThread) : previous_(Thread::GetCurrent()) 26 { 27 Thread::SetCurrent(gcThread); 28 } 29 ~GcThreadScope()30 ~GcThreadScope() 31 { 32 Thread::SetCurrent(previous_); 33 } 34 35 DEFAULT_COPY_SEMANTIC(GcThreadScope); 36 DEFAULT_MOVE_SEMANTIC(GcThreadScope); 37 38 private: 39 Thread *previous_; 40 }; 41 42 template <typename LanguageConfig> 43 class G1EvacuateRegionsTask : public GCWorkersTask { 44 public: G1EvacuateRegionsTask(G1EvacuateRegionsWorkerState<LanguageConfig> * state)45 explicit G1EvacuateRegionsTask(G1EvacuateRegionsWorkerState<LanguageConfig> *state) 46 : GCWorkersTask(GCWorkersTaskTypes::TASK_EVACUATE_REGIONS, state) 47 { 48 } 49 50 DEFAULT_COPY_SEMANTIC(G1EvacuateRegionsTask); 51 DEFAULT_MOVE_SEMANTIC(G1EvacuateRegionsTask); 52 ~G1EvacuateRegionsTask() = default; 53 Work()54 void Work() 55 { 56 GcThreadScope gcThreadScope(GetState()->GetShared()->GetGcThread()); 57 GetState()->Work(); 58 } 59 60 private: GetState()61 G1EvacuateRegionsWorkerState<LanguageConfig> *GetState() const 62 { 63 return static_cast<G1EvacuateRegionsWorkerState<LanguageConfig> *>(storage_); 64 } 65 }; 66 67 template <class LanguageConfig> 68 class ParallelCompactionTask { 69 public: ParallelCompactionTask(G1GC<LanguageConfig> * gc,ObjectAllocatorG1<LanguageConfig::MT_MODE> * objectAllocator,RemSet<> * remset,const CollectionSet & collectionSet)70 ParallelCompactionTask(G1GC<LanguageConfig> *gc, ObjectAllocatorG1<LanguageConfig::MT_MODE> *objectAllocator, 71 RemSet<> *remset, const CollectionSet &collectionSet) 72 : gc_(gc), 73 internalAllocator_(gc->GetInternalAllocator()), 74 objectAllocator_(objectAllocator), 75 shared_(Thread::GetCurrent(), gc->GetSettings()->GCWorkersCount(), remset), 76 queues_(shared_.GetWorkersCount()) 77 { 78 for (auto *region : collectionSet) { 79 auto allocated = region->GetAllocatedBytes(); 80 if (region->HasFlag(RegionFlag::IS_EDEN)) { 81 allocatedBytesYoung_ += allocated; 82 } else { 83 allocatedBytesOld_ += allocated; 84 } 85 } 86 } 87 88 NO_COPY_SEMANTIC(ParallelCompactionTask); 89 NO_MOVE_SEMANTIC(ParallelCompactionTask); 90 ~ParallelCompactionTask()91 ~ParallelCompactionTask() 92 { 93 for (auto *state : workerStates_) { 94 internalAllocator_->Delete(state); 95 } 96 } 97 Run()98 void Run() 99 { 100 Submit(); 101 gc_->GetWorkersTaskPool()->WaitUntilTasksEnd(); 102 LOG_IF(gc_->GetSettings()->LogDetailedGCInfoEnabled(), INFO, GC) 103 << "Waited all workers for " 104 << ark::helpers::TimeConverter(ark::time::GetCurrentTimeInNanos() - beforeSubmitTime_); 105 } 106 FlushDirtyCards(GCG1BarrierSet::ThreadLocalCardQueues * queue)107 void FlushDirtyCards(GCG1BarrierSet::ThreadLocalCardQueues *queue) 108 { 109 for (auto *state : workerStates_) { 110 state->VisitCards([queue](auto *card) { 111 if (!card->IsMarked()) { 112 card->Mark(); 113 queue->push_back(card); 114 } 115 }); 116 } 117 } 118 Finish()119 void Finish() 120 { 121 for (auto *state : workerStates_) { 122 state->GetRegionTo()->SetLiveBytes(state->GetRegionTo()->GetLiveBytes() + state->GetLiveBytes()); 123 objectAllocator_->template PushToOldRegionQueue<true>(state->GetRegionTo()); 124 125 copiedBytesYoung_ += state->GetCopiedBytesYoung(); 126 copiedObjectsYoung_ += state->GetCopiedObjectsYoung(); 127 128 copiedBytesOld_ += state->GetCopiedBytesOld(); 129 copiedObjectsOld_ += state->GetCopiedObjectsOld(); 130 } 131 132 if (gc_->GetSettings()->LogDetailedGCInfoEnabled()) { 133 DumpStats(); 134 } 135 } 136 GetCopiedBytesYoung()137 size_t GetCopiedBytesYoung() const 138 { 139 return copiedBytesYoung_; 140 } 141 GetCopiedObjectsYoung()142 size_t GetCopiedObjectsYoung() const 143 { 144 return copiedObjectsYoung_; 145 } 146 GetCopiedBytesOld()147 size_t GetCopiedBytesOld() const 148 { 149 return copiedBytesOld_; 150 } 151 GetCopiedObjectsOld()152 size_t GetCopiedObjectsOld() const 153 { 154 return copiedObjectsOld_; 155 } 156 GetFreedBytesYoung()157 size_t GetFreedBytesYoung() const 158 { 159 return allocatedBytesYoung_ - copiedBytesYoung_; 160 } 161 GetFreedBytesOld()162 size_t GetFreedBytesOld() const 163 { 164 return allocatedBytesOld_ - copiedBytesOld_; 165 } 166 167 private: 168 using TaskQueue = PandaVector<typename ObjectReference<LanguageConfig::LANG_TYPE>::Type>; 169 Submit()170 void Submit() 171 { 172 beforeSubmitTime_ = ark::time::GetCurrentTimeInNanos(); 173 auto workersCount = shared_.GetWorkersCount(); 174 for (size_t i = 0; i < workersCount; i++) { 175 auto *state = internalAllocator_->template New<G1EvacuateRegionsWorkerState<LanguageConfig>>( 176 gc_, i, &queues_[i], &shared_); 177 bool added = gc_->GetWorkersTaskPool()->AddTask(G1EvacuateRegionsTask(state)); 178 if (!added) { 179 LOG(INFO, GC) << "Not enough workers to add task #" << i; 180 state->Work(); 181 } 182 workerStates_.push_back(state); 183 } 184 } 185 DumpStats()186 void DumpStats() const 187 { 188 for (auto *state : workerStates_) { 189 LOG(INFO, GC) << "Worker #" << state->GetId() << " started +" 190 << ark::helpers::TimeConverter(state->GetTaskStart() - beforeSubmitTime_); 191 LOG(INFO, GC) << "Worker #" << state->GetId() << " finished +" 192 << ark::helpers::TimeConverter(state->GetTaskEnd() - beforeSubmitTime_); 193 LOG(INFO, GC) << "Worker #" << state->GetId() << " duration " 194 << ark::helpers::TimeConverter(state->GetTaskEnd() - state->GetTaskStart()); 195 state->DumpStat(); 196 } 197 } 198 199 G1GC<LanguageConfig> *gc_; 200 InternalAllocatorPtr internalAllocator_; 201 ObjectAllocatorG1<LanguageConfig::MT_MODE> *objectAllocator_; 202 PandaVector<G1EvacuateRegionsWorkerState<LanguageConfig> *> workerStates_; 203 SharedState shared_; 204 PandaVector<TaskQueue> queues_; 205 206 uint64_t beforeSubmitTime_ {0}; 207 size_t allocatedBytesYoung_ {0}; 208 size_t allocatedBytesOld_ {0}; 209 210 size_t copiedBytesYoung_ {0}; 211 size_t copiedObjectsYoung_ {0}; 212 size_t copiedBytesOld_ {0}; 213 size_t copiedObjectsOld_ {0}; 214 }; 215 216 } // namespace ark::mem 217 #endif 218