[api][profiler] Surface CpuProfiler memory in HeapCodeStatistics
The goal of the PR is to add to telemetry a metric estimating the space occupied by the codemap retained by a CpuProfiler and its underlying CodeObserver. This change is motivated by the addition of kEagerLogger to CpuProfiler which when enabled let a CpuProfiler build a CodeMap without an active session. This metric will help us understand better the space consumed by a profiler in that scenario and will also help detect memory leaks. Bug: chromium:1241491 Change-Id: Iadb1ed52b4c1ac70bc554942b4fa795cdf1212f3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3224567 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Auto-Submit: Corentin Pescheloche <cpescheloche@fb.com> Cr-Commit-Position: refs/heads/main@{#77703}
This commit is contained in:
parent
71bffcced0
commit
0bf11af7e4
@ -201,11 +201,13 @@ class V8_EXPORT HeapCodeStatistics {
|
||||
size_t code_and_metadata_size() { return code_and_metadata_size_; }
|
||||
size_t bytecode_and_metadata_size() { return bytecode_and_metadata_size_; }
|
||||
size_t external_script_source_size() { return external_script_source_size_; }
|
||||
size_t cpu_profiler_metadata_size() { return cpu_profiler_metadata_size_; }
|
||||
|
||||
private:
|
||||
size_t code_and_metadata_size_;
|
||||
size_t bytecode_and_metadata_size_;
|
||||
size_t external_script_source_size_;
|
||||
size_t cpu_profiler_metadata_size_;
|
||||
|
||||
friend class Isolate;
|
||||
};
|
||||
|
@ -6144,7 +6144,8 @@ HeapObjectStatistics::HeapObjectStatistics()
|
||||
HeapCodeStatistics::HeapCodeStatistics()
|
||||
: code_and_metadata_size_(0),
|
||||
bytecode_and_metadata_size_(0),
|
||||
external_script_source_size_(0) {}
|
||||
external_script_source_size_(0),
|
||||
cpu_profiler_metadata_size_(0) {}
|
||||
|
||||
bool v8::V8::InitializeICU(const char* icu_data_file) {
|
||||
return i::InitializeICU(icu_data_file);
|
||||
@ -8897,6 +8898,10 @@ bool Isolate::GetHeapCodeAndMetadataStatistics(
|
||||
isolate->bytecode_and_metadata_size();
|
||||
code_statistics->external_script_source_size_ =
|
||||
isolate->external_script_source_size();
|
||||
code_statistics->cpu_profiler_metadata_size_ =
|
||||
i::CpuProfiler::GetAllProfilersMemorySize(
|
||||
reinterpret_cast<i::Isolate*>(isolate));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -471,6 +471,16 @@ class CpuProfilersManager {
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetAllProfilersMemorySize(Isolate* isolate) {
|
||||
base::MutexGuard lock(&mutex_);
|
||||
size_t estimated_memory = 0;
|
||||
auto range = profilers_.equal_range(isolate);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
estimated_memory += it->second->GetEstimatedMemoryUsage();
|
||||
}
|
||||
return estimated_memory;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_multimap<Isolate*, CpuProfiler*> profilers_;
|
||||
base::Mutex mutex_;
|
||||
@ -578,6 +588,15 @@ void CpuProfiler::CollectSample() {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
size_t CpuProfiler::GetAllProfilersMemorySize(Isolate* isolate) {
|
||||
return GetProfilersManager()->GetAllProfilersMemorySize(isolate);
|
||||
}
|
||||
|
||||
size_t CpuProfiler::GetEstimatedMemoryUsage() const {
|
||||
return code_observer_->GetEstimatedMemoryUsage();
|
||||
}
|
||||
|
||||
CpuProfilingStatus CpuProfiler::StartProfiling(
|
||||
const char* title, CpuProfilingOptions options,
|
||||
std::unique_ptr<DiscardedSamplesDelegate> delegate) {
|
||||
|
@ -333,6 +333,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
||||
CpuProfiler& operator=(const CpuProfiler&) = delete;
|
||||
|
||||
static void CollectSample(Isolate* isolate);
|
||||
static size_t GetAllProfilersMemorySize(Isolate* isolate);
|
||||
|
||||
using ProfilingMode = v8::CpuProfilingMode;
|
||||
using NamingMode = v8::CpuProfilingNamingMode;
|
||||
@ -343,6 +344,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
||||
void set_sampling_interval(base::TimeDelta value);
|
||||
void set_use_precise_sampling(bool);
|
||||
void CollectSample();
|
||||
size_t GetEstimatedMemoryUsage() const;
|
||||
StartProfilingStatus StartProfiling(
|
||||
const char* title, CpuProfilingOptions options = {},
|
||||
std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
|
||||
|
@ -4331,7 +4331,7 @@ TEST(ClearUnusedWithEagerLogging) {
|
||||
|
||||
CodeMap* code_map = profiler.code_map_for_test();
|
||||
size_t initial_size = code_map->size();
|
||||
size_t profiler_size = code_observer->GetEstimatedMemoryUsage();
|
||||
size_t profiler_size = profiler.GetEstimatedMemoryUsage();
|
||||
|
||||
{
|
||||
// Create and run a new script and function, generating 2 code objects.
|
||||
@ -4343,7 +4343,8 @@ TEST(ClearUnusedWithEagerLogging) {
|
||||
"function some_func() {}"
|
||||
"some_func();");
|
||||
CHECK_GT(code_map->size(), initial_size);
|
||||
CHECK_GT(code_observer->GetEstimatedMemoryUsage(), profiler_size);
|
||||
CHECK_GT(profiler.GetEstimatedMemoryUsage(), profiler_size);
|
||||
CHECK_GT(profiler.GetAllProfilersMemorySize(isolate), profiler_size);
|
||||
}
|
||||
|
||||
// Clear the compilation cache so that there are no more references to the
|
||||
@ -4354,7 +4355,8 @@ TEST(ClearUnusedWithEagerLogging) {
|
||||
|
||||
// Verify that the CodeMap's size is unchanged post-GC.
|
||||
CHECK_EQ(code_map->size(), initial_size);
|
||||
CHECK_EQ(code_observer->GetEstimatedMemoryUsage(), profiler_size);
|
||||
CHECK_EQ(profiler.GetEstimatedMemoryUsage(), profiler_size);
|
||||
CHECK_EQ(profiler.GetAllProfilersMemorySize(isolate), profiler_size);
|
||||
}
|
||||
|
||||
// Ensure that ProfilerCodeObserver doesn't compute estimated size when race
|
||||
@ -4367,20 +4369,20 @@ TEST(SkipEstimatedSizeWhenActiveProfiling) {
|
||||
|
||||
CodeEntryStorage storage;
|
||||
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
|
||||
ProfilerCodeObserver* code_observer =
|
||||
new ProfilerCodeObserver(isolate, storage);
|
||||
|
||||
CpuProfiler profiler(isolate, kDebugNaming, kEagerLogging, profiles, nullptr,
|
||||
nullptr, code_observer);
|
||||
nullptr, new ProfilerCodeObserver(isolate, storage));
|
||||
|
||||
CHECK_GT(code_observer->GetEstimatedMemoryUsage(), 0);
|
||||
CHECK_GT(profiler.GetAllProfilersMemorySize(isolate), 0);
|
||||
CHECK_GT(profiler.GetEstimatedMemoryUsage(), 0);
|
||||
|
||||
profiler.StartProfiling("");
|
||||
CHECK_EQ(code_observer->GetEstimatedMemoryUsage(), 0);
|
||||
CHECK_EQ(profiler.GetAllProfilersMemorySize(isolate), 0);
|
||||
CHECK_EQ(profiler.GetEstimatedMemoryUsage(), 0);
|
||||
|
||||
profiler.StopProfiling("");
|
||||
|
||||
CHECK_GT(code_observer->GetEstimatedMemoryUsage(), 0);
|
||||
CHECK_GT(profiler.GetAllProfilersMemorySize(isolate), 0);
|
||||
CHECK_GT(profiler.GetEstimatedMemoryUsage(), 0);
|
||||
}
|
||||
|
||||
} // namespace test_cpu_profiler
|
||||
|
Loading…
Reference in New Issue
Block a user