* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common_components/heap/collector/gc_stats.h"
#include "base_runtime.h"
#include "common_components/base/time_utils.h"
#include "common_components/heap/heap.h"
#include "common_components/log/log.h"
namespace common {
size_t g_gcCount = 0;
uint64_t g_gcTotalTimeUs = 0;
size_t g_gcCollectedTotalBytes = 0;
size_t g_fullGCCount = 0;
double g_fullGCMeanRate = 0.0;
uint64_t GCStats::prevGcStartTime = TimeUtil::NanoSeconds() - LONG_MIN_HEU_GC_INTERVAL_NS;
uint64_t GCStats::prevGcFinishTime = TimeUtil::NanoSeconds() - LONG_MIN_HEU_GC_INTERVAL_NS;
void GCStats::Init()
{
isConcurrentMark = false;
async = false;
gcStartTime = TimeUtil::NanoSeconds();
gcEndTime = TimeUtil::NanoSeconds();
totalSTWTime = 0;
maxSTWTime = 0;
collectedObjects = 0;
collectedBytes = 0;
fromSpaceSize = 0;
smallGarbageSize = 0;
nonMovableSpaceSize = 0;
nonMovableGarbageSize = 0;
largeSpaceSize = 0;
largeGarbageSize = 0;
liveBytesBeforeGC = 0;
liveBytesAfterGC = 0;
garbageRatio = 0.0;
collectionRate = 0.0;
heapThreshold = std::min(BaseRuntime::GetInstance()->GetGCParam().gcThreshold, 20 * MB);
heapThreshold = std::min(static_cast<size_t>(Heap::GetHeap().GetMaxCapacity() * 0.2), heapThreshold);
targetFootprint = heapThreshold;
shouldRequestYoung = false;
}
void GCStats::Dump() const
{
size_t liveSize = Heap::GetHeap().GetAllocatedSize();
size_t heapSize = Heap::GetHeap().GetUsedPageSize();
double utilization = (heapSize == 0) ? 0 : (static_cast<double>(liveSize) / heapSize);
std::string maxSTWTime = PrettyOrderMathNano(MaxSTWTime(), "s");
std::string totalSTWTime = PrettyOrderMathNano(TotalSTWTime(), "s");
std::string totalGCTime = PrettyOrderMathNano(gcEndTime - gcStartTime, "s");
std::ostringstream oss;
oss <<
"GC for " << g_gcRequests[reason].name << ": " << (async ? "async:" : "sync: ") <<
"gcType: " << GCTypeToString(gcType) << ", collected bytes: " <<
collectedBytes << "->" << PrettyOrderInfo(collectedBytes, "B") << ", " <<
"->" << PrettyOrderInfo(liveSize, "B") << "/" << heapSize << "->" <<
PrettyOrderInfo(heapSize, "B") << ", max pause: " << MaxSTWTime() <<
"->" << maxSTWTime << ", total pause: " << TotalSTWTime() << "->" << totalSTWTime <<
", total GC time: " << (gcEndTime - gcStartTime) << "->" << totalGCTime;
VLOG(INFO, oss.str().c_str());
VLOG(DEBUG, "allocated size: %s, heap size: %s, heap utilization: %.2f%%", Pretty(liveSize).c_str(),
Pretty(heapSize).c_str(), utilization * 100);
OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::GCStatsDump", (
"collectedObjects:" + std::to_string(collectedObjects) +
";collectedBytes:" + std::to_string(collectedBytes) +
";liveSize:" + std::to_string(liveSize) +
";heapSize:" + std::to_string(heapSize) +
";max pause:" + maxSTWTime +
";total pause:" + totalSTWTime +
";total GC time:" + totalGCTime
).c_str());
}
}