Commit 920d2d6b authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

[sampling heap profiler] Report modules through protocol.

To allow external symbolization the profile has to include modules info.

BUG=803276
TBR=pfeldman@chromium.org

Change-Id: I0802678210e07ec89a2d2e5eae9a02f7d5dc1568
Reviewed-on: https://chromium-review.googlesource.com/1147525Reviewed-by: default avatarAlexei Filippov <alph@chromium.org>
Reviewed-by: default avatarPavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarMike Wittman <wittman@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581323}
parent d027e357
...@@ -30,4 +30,12 @@ const ModuleCache::Module& ModuleCache::GetModuleForAddress(uintptr_t address) { ...@@ -30,4 +30,12 @@ const ModuleCache::Module& ModuleCache::GetModuleForAddress(uintptr_t address) {
.first->second; .first->second;
} }
std::vector<const ModuleCache::Module*> ModuleCache::GetModules() const {
std::vector<const Module*> result;
result.reserve(modules_cache_map_.size());
for (const auto& it : modules_cache_map_)
result.push_back(&it.second);
return result;
}
} // namespace base } // namespace base
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define BASE_SAMPLING_HEAP_PROFILER_MODULE_CACHE_H_ #define BASE_SAMPLING_HEAP_PROFILER_MODULE_CACHE_H_
#include <map> #include <map>
#include <vector>
#include "base/profiler/stack_sampling_profiler.h" #include "base/profiler/stack_sampling_profiler.h"
...@@ -19,6 +20,7 @@ class BASE_EXPORT ModuleCache { ...@@ -19,6 +20,7 @@ class BASE_EXPORT ModuleCache {
~ModuleCache(); ~ModuleCache();
const Module& GetModuleForAddress(uintptr_t address); const Module& GetModuleForAddress(uintptr_t address);
std::vector<const Module*> GetModules() const;
private: private:
std::map<uintptr_t, Module> modules_cache_map_; std::map<uintptr_t, Module> modules_cache_map_;
......
...@@ -19,8 +19,10 @@ int AFunctionForTest() { ...@@ -19,8 +19,10 @@ int AFunctionForTest() {
// addresses within the module. // addresses within the module.
#if defined(OS_MACOSX) && !defined(OS_IOS) #if defined(OS_MACOSX) && !defined(OS_IOS)
#define MAYBE_ModuleCache ModuleCache #define MAYBE_ModuleCache ModuleCache
#define MAYBE_ModulesList ModulesList
#else #else
#define MAYBE_ModuleCache DISABLED_ModuleCache #define MAYBE_ModuleCache DISABLED_ModuleCache
#define MAYBE_ModulesList DISABLED_ModulesList
#endif #endif
TEST_F(ModuleCacheTest, MAYBE_ModuleCache) { TEST_F(ModuleCacheTest, MAYBE_ModuleCache) {
uintptr_t ptr1 = reinterpret_cast<uintptr_t>(&AFunctionForTest); uintptr_t ptr1 = reinterpret_cast<uintptr_t>(&AFunctionForTest);
...@@ -34,6 +36,15 @@ TEST_F(ModuleCacheTest, MAYBE_ModuleCache) { ...@@ -34,6 +36,15 @@ TEST_F(ModuleCacheTest, MAYBE_ModuleCache) {
EXPECT_GT(module1.base_address + module1.size, ptr2); EXPECT_GT(module1.base_address + module1.size, ptr2);
} }
TEST_F(ModuleCacheTest, MAYBE_ModulesList) {
ModuleCache cache;
uintptr_t ptr = reinterpret_cast<uintptr_t>(&AFunctionForTest);
const ModuleCache::Module& module = cache.GetModuleForAddress(ptr);
EXPECT_TRUE(module.is_valid);
EXPECT_EQ(1u, cache.GetModules().size());
EXPECT_EQ(&module, cache.GetModules().front());
}
TEST_F(ModuleCacheTest, InvalidModule) { TEST_F(ModuleCacheTest, InvalidModule) {
ModuleCache cache; ModuleCache cache;
const ModuleCache::Module& invalid_module = cache.GetModuleForAddress(1); const ModuleCache::Module& invalid_module = cache.GetModuleForAddress(1);
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
#include "content/browser/devtools/protocol/memory_handler.h" #include "content/browser/devtools/protocol/memory_handler.h"
#include <cinttypes>
#include "base/memory/memory_pressure_listener.h" #include "base/memory/memory_pressure_listener.h"
#include "base/sampling_heap_profiler/module_cache.h"
#include "base/sampling_heap_profiler/sampling_heap_profiler.h" #include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
...@@ -33,6 +36,7 @@ void MemoryHandler::SetRenderer(int process_host_id, ...@@ -33,6 +36,7 @@ void MemoryHandler::SetRenderer(int process_host_id,
Response MemoryHandler::GetBrowserSamplingProfile( Response MemoryHandler::GetBrowserSamplingProfile(
std::unique_ptr<Memory::SamplingProfile>* out_profile) { std::unique_ptr<Memory::SamplingProfile>* out_profile) {
base::ModuleCache module_cache;
std::unique_ptr<Array<Memory::SamplingProfileNode>> samples = std::unique_ptr<Array<Memory::SamplingProfileNode>> samples =
Array<Memory::SamplingProfileNode>::create(); Array<Memory::SamplingProfileNode>::create();
std::vector<base::SamplingHeapProfiler::Sample> raw_samples = std::vector<base::SamplingHeapProfiler::Sample> raw_samples =
...@@ -40,8 +44,11 @@ Response MemoryHandler::GetBrowserSamplingProfile( ...@@ -40,8 +44,11 @@ Response MemoryHandler::GetBrowserSamplingProfile(
for (auto& sample : raw_samples) { for (auto& sample : raw_samples) {
std::unique_ptr<Array<String>> stack = Array<String>::create(); std::unique_ptr<Array<String>> stack = Array<String>::create();
for (auto* frame : sample.stack) for (const void* frame : sample.stack) {
stack->addItem(base::StringPrintf("%p", frame)); uintptr_t address = reinterpret_cast<uintptr_t>(frame);
module_cache.GetModuleForAddress(address); // Populates module_cache.
stack->addItem(base::StringPrintf("0x%" PRIxPTR, address));
}
samples->addItem(Memory::SamplingProfileNode::Create() samples->addItem(Memory::SamplingProfileNode::Create()
.SetSize(sample.size) .SetSize(sample.size)
.SetTotal(sample.total) .SetTotal(sample.total)
...@@ -49,8 +56,23 @@ Response MemoryHandler::GetBrowserSamplingProfile( ...@@ -49,8 +56,23 @@ Response MemoryHandler::GetBrowserSamplingProfile(
.Build()); .Build());
} }
*out_profile = std::unique_ptr<Array<Memory::Module>> modules =
Memory::SamplingProfile::Create().SetSamples(std::move(samples)).Build(); Array<Memory::Module>::create();
for (const auto* module : module_cache.GetModules()) {
modules->addItem(Memory::Module::Create()
.SetName(base::StringPrintf(
"%" PRIsFP, module->filename.value().c_str()))
.SetUuid(module->id)
.SetBaseAddress(base::StringPrintf(
"0x%" PRIxPTR, module->base_address))
.SetSize(static_cast<double>(module->size))
.Build());
}
*out_profile = Memory::SamplingProfile::Create()
.SetSamples(std::move(samples))
.SetModules(std::move(modules))
.Build();
return Response::OK(); return Response::OK();
} }
......
include_rules = [ include_rules = [
"+base/time/time_override.h", "+base/time/time_override.h",
"+base/sampling_heap_profiler/module_cache.h",
"+base/sampling_heap_profiler/sampling_heap_profiler.h", "+base/sampling_heap_profiler/sampling_heap_profiler.h",
# for base::GetUniqueIdForProcess # for base::GetUniqueIdForProcess
"+base/process/process_handle.h", "+base/process/process_handle.h",
......
...@@ -3414,6 +3414,20 @@ experimental domain Memory ...@@ -3414,6 +3414,20 @@ experimental domain Memory
type SamplingProfile extends object type SamplingProfile extends object
properties properties
array of SamplingProfileNode samples array of SamplingProfileNode samples
array of Module modules
# Executable module information
type Module extends object
properties
# Name of the module.
string name
# UUID of the module.
string uuid
# Base address where the module is loaded into memory. Encoded as a decimal
# or hexadecimal (0x prefixed) string.
string baseAddress
# Size of the module in bytes.
number size
# Network domain allows tracking network activities of the page. It exposes information about http, # Network domain allows tracking network activities of the page. It exposes information about http,
# file, data and other requests and responses, their headers, bodies, timing, etc. # file, data and other requests and responses, their headers, bodies, timing, etc.
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <cstdio> #include <cstdio>
#include "base/debug/stack_trace.h" #include "base/debug/stack_trace.h"
#include "base/sampling_heap_profiler/module_cache.h"
#include "base/sampling_heap_profiler/sampling_heap_profiler.h" #include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h"
...@@ -110,6 +111,7 @@ Response InspectorMemoryAgent::getSamplingProfile( ...@@ -110,6 +111,7 @@ Response InspectorMemoryAgent::getSamplingProfile(
std::unique_ptr<protocol::Memory::SamplingProfile> std::unique_ptr<protocol::Memory::SamplingProfile>
InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) { InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) {
base::ModuleCache module_cache;
std::unique_ptr<protocol::Array<protocol::Memory::SamplingProfileNode>> std::unique_ptr<protocol::Array<protocol::Memory::SamplingProfileNode>>
samples = samples =
protocol::Array<protocol::Memory::SamplingProfileNode>::create(); protocol::Array<protocol::Memory::SamplingProfileNode>::create();
...@@ -119,6 +121,10 @@ InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) { ...@@ -119,6 +121,10 @@ InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) {
for (auto& it : raw_samples) { for (auto& it : raw_samples) {
std::unique_ptr<protocol::Array<protocol::String>> stack = std::unique_ptr<protocol::Array<protocol::String>> stack =
protocol::Array<protocol::String>::create(); protocol::Array<protocol::String>::create();
for (const void* frame : it.stack) {
uintptr_t address = reinterpret_cast<uintptr_t>(frame);
module_cache.GetModuleForAddress(address); // Populates module_cache.
}
std::vector<std::string> source_stack = Symbolize(it.stack); std::vector<std::string> source_stack = Symbolize(it.stack);
for (auto& it2 : source_stack) for (auto& it2 : source_stack)
stack->addItem(it2.c_str()); stack->addItem(it2.c_str());
...@@ -145,8 +151,21 @@ InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) { ...@@ -145,8 +151,21 @@ InspectorMemoryAgent::GetSamplingProfileById(uint32_t id) {
.build()); .build());
} }
std::unique_ptr<protocol::Array<protocol::Memory::Module>> modules =
protocol::Array<protocol::Memory::Module>::create();
for (const auto* module : module_cache.GetModules()) {
modules->addItem(
protocol::Memory::Module::create()
.setName(module->filename.value().c_str())
.setUuid(module->id.c_str())
.setBaseAddress(String::Format("0x%" PRIxPTR, module->base_address))
.setSize(static_cast<double>(module->size))
.build());
}
return protocol::Memory::SamplingProfile::create() return protocol::Memory::SamplingProfile::create()
.setSamples(std::move(samples)) .setSamples(std::move(samples))
.setModules(std::move(modules))
.build(); .build();
} }
...@@ -175,21 +194,19 @@ std::vector<std::string> InspectorMemoryAgent::Symbolize( ...@@ -175,21 +194,19 @@ std::vector<std::string> InspectorMemoryAgent::Symbolize(
line.substr(space_pos == std::string::npos ? 0 : space_pos + 1); line.substr(space_pos == std::string::npos ? 0 : space_pos + 1);
symbols_cache_.insert(addresses_to_symbolize[i], name); symbols_cache_.insert(addresses_to_symbolize[i], name);
} }
#endif
std::vector<std::string> result;
for (void* address : addresses)
result.push_back(symbols_cache_.at(address));
return result;
#else
std::vector<std::string> result; std::vector<std::string> result;
for (void* address : addresses) { for (void* address : addresses) {
char buffer[20]; char buffer[20];
std::snprintf(buffer, sizeof(buffer), "%p", address); std::snprintf(buffer, sizeof(buffer), "0x%" PRIxPTR,
result.push_back(buffer); reinterpret_cast<uintptr_t>(address));
if (symbols_cache_.Contains(address))
result.push_back(std::string(buffer) + " " + symbols_cache_.at(address));
else
result.push_back(buffer);
} }
return result; return result;
#endif
} }
} // namespace blink } // namespace blink
...@@ -307,6 +307,7 @@ _CONFIG = [ ...@@ -307,6 +307,7 @@ _CONFIG = [
{ {
'paths': ['third_party/blink/renderer/core/inspector/inspector_memory_agent.cc'], 'paths': ['third_party/blink/renderer/core/inspector/inspector_memory_agent.cc'],
'allowed': [ 'allowed': [
'base::ModuleCache',
'base::SamplingHeapProfiler', 'base::SamplingHeapProfiler',
], ],
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment