[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 code_and_metadata_size() { return code_and_metadata_size_; }
|
||||||
size_t bytecode_and_metadata_size() { return bytecode_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 external_script_source_size() { return external_script_source_size_; }
|
||||||
|
size_t cpu_profiler_metadata_size() { return cpu_profiler_metadata_size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t code_and_metadata_size_;
|
size_t code_and_metadata_size_;
|
||||||
size_t bytecode_and_metadata_size_;
|
size_t bytecode_and_metadata_size_;
|
||||||
size_t external_script_source_size_;
|
size_t external_script_source_size_;
|
||||||
|
size_t cpu_profiler_metadata_size_;
|
||||||
|
|
||||||
friend class Isolate;
|
friend class Isolate;
|
||||||
};
|
};
|
||||||
|
@ -6144,7 +6144,8 @@ HeapObjectStatistics::HeapObjectStatistics()
|
|||||||
HeapCodeStatistics::HeapCodeStatistics()
|
HeapCodeStatistics::HeapCodeStatistics()
|
||||||
: code_and_metadata_size_(0),
|
: code_and_metadata_size_(0),
|
||||||
bytecode_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) {
|
bool v8::V8::InitializeICU(const char* icu_data_file) {
|
||||||
return i::InitializeICU(icu_data_file);
|
return i::InitializeICU(icu_data_file);
|
||||||
@ -8897,6 +8898,10 @@ bool Isolate::GetHeapCodeAndMetadataStatistics(
|
|||||||
isolate->bytecode_and_metadata_size();
|
isolate->bytecode_and_metadata_size();
|
||||||
code_statistics->external_script_source_size_ =
|
code_statistics->external_script_source_size_ =
|
||||||
isolate->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;
|
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:
|
private:
|
||||||
std::unordered_multimap<Isolate*, CpuProfiler*> profilers_;
|
std::unordered_multimap<Isolate*, CpuProfiler*> profilers_;
|
||||||
base::Mutex mutex_;
|
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(
|
CpuProfilingStatus CpuProfiler::StartProfiling(
|
||||||
const char* title, CpuProfilingOptions options,
|
const char* title, CpuProfilingOptions options,
|
||||||
std::unique_ptr<DiscardedSamplesDelegate> delegate) {
|
std::unique_ptr<DiscardedSamplesDelegate> delegate) {
|
||||||
|
@ -333,6 +333,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
|||||||
CpuProfiler& operator=(const CpuProfiler&) = delete;
|
CpuProfiler& operator=(const CpuProfiler&) = delete;
|
||||||
|
|
||||||
static void CollectSample(Isolate* isolate);
|
static void CollectSample(Isolate* isolate);
|
||||||
|
static size_t GetAllProfilersMemorySize(Isolate* isolate);
|
||||||
|
|
||||||
using ProfilingMode = v8::CpuProfilingMode;
|
using ProfilingMode = v8::CpuProfilingMode;
|
||||||
using NamingMode = v8::CpuProfilingNamingMode;
|
using NamingMode = v8::CpuProfilingNamingMode;
|
||||||
@ -343,6 +344,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
|
|||||||
void set_sampling_interval(base::TimeDelta value);
|
void set_sampling_interval(base::TimeDelta value);
|
||||||
void set_use_precise_sampling(bool);
|
void set_use_precise_sampling(bool);
|
||||||
void CollectSample();
|
void CollectSample();
|
||||||
|
size_t GetEstimatedMemoryUsage() const;
|
||||||
StartProfilingStatus StartProfiling(
|
StartProfilingStatus StartProfiling(
|
||||||
const char* title, CpuProfilingOptions options = {},
|
const char* title, CpuProfilingOptions options = {},
|
||||||
std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
|
std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
|
||||||
|
@ -4331,7 +4331,7 @@ TEST(ClearUnusedWithEagerLogging) {
|
|||||||
|
|
||||||
CodeMap* code_map = profiler.code_map_for_test();
|
CodeMap* code_map = profiler.code_map_for_test();
|
||||||
size_t initial_size = code_map->size();
|
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.
|
// Create and run a new script and function, generating 2 code objects.
|
||||||
@ -4343,7 +4343,8 @@ TEST(ClearUnusedWithEagerLogging) {
|
|||||||
"function some_func() {}"
|
"function some_func() {}"
|
||||||
"some_func();");
|
"some_func();");
|
||||||
CHECK_GT(code_map->size(), initial_size);
|
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
|
// 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.
|
// Verify that the CodeMap's size is unchanged post-GC.
|
||||||
CHECK_EQ(code_map->size(), initial_size);
|
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
|
// Ensure that ProfilerCodeObserver doesn't compute estimated size when race
|
||||||
@ -4367,20 +4369,20 @@ TEST(SkipEstimatedSizeWhenActiveProfiling) {
|
|||||||
|
|
||||||
CodeEntryStorage storage;
|
CodeEntryStorage storage;
|
||||||
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
|
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
|
||||||
ProfilerCodeObserver* code_observer =
|
|
||||||
new ProfilerCodeObserver(isolate, storage);
|
|
||||||
|
|
||||||
CpuProfiler profiler(isolate, kDebugNaming, kEagerLogging, profiles, nullptr,
|
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("");
|
profiler.StartProfiling("");
|
||||||
CHECK_EQ(code_observer->GetEstimatedMemoryUsage(), 0);
|
CHECK_EQ(profiler.GetAllProfilersMemorySize(isolate), 0);
|
||||||
|
CHECK_EQ(profiler.GetEstimatedMemoryUsage(), 0);
|
||||||
|
|
||||||
profiler.StopProfiling("");
|
profiler.StopProfiling("");
|
||||||
|
|
||||||
CHECK_GT(code_observer->GetEstimatedMemoryUsage(), 0);
|
CHECK_GT(profiler.GetAllProfilersMemorySize(isolate), 0);
|
||||||
|
CHECK_GT(profiler.GetEstimatedMemoryUsage(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test_cpu_profiler
|
} // namespace test_cpu_profiler
|
||||||
|
Loading…
Reference in New Issue
Block a user