Commit 8ddf74f6 authored by Piotr Roguski's avatar Piotr Roguski Committed by Commit Bot

Adds proto writer for memory dump.

Adding TracingObserverProto for serializing memory dump in to proto format needed for migration of memory-infra to Perfetto. See crbug.com/1098746 for more details.

Bug: 1098746
Change-Id: If78a00672263f0cb061d5f505a62da912c2d7091
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2324841
Commit-Queue: Piotr Roguski <piotr.roguski@mobica.com>
Commit-Queue: ssid <ssid@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarssid <ssid@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarErik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#813290}
parent e2c69d52
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/traced_value.h" #include "base/trace_event/traced_value.h"
#include "base/values.h" #include "base/values.h"
#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
namespace base { namespace base {
namespace trace_event { namespace trace_event {
...@@ -90,6 +92,52 @@ void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { ...@@ -90,6 +92,52 @@ void MemoryAllocatorDump::AsValueInto(TracedValue* value) const {
value->EndDictionary(); // "allocator_name/heap_subheap": { ... } value->EndDictionary(); // "allocator_name/heap_subheap": { ... }
} }
void MemoryAllocatorDump::AsProtoInto(
perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::
MemoryNode* memory_node) const {
memory_node->set_id(guid_.ToUint64());
memory_node->set_absolute_name(absolute_name_);
if (flags() & WEAK) {
memory_node->set_weak(true);
}
for (const Entry& entry : entries_) {
if (entry.name == "size") {
DCHECK_EQ(entry.entry_type, Entry::EntryType::kUint64);
DCHECK_EQ(entry.units, "kBytes");
memory_node->set_size_bytes(entry.value_uint64);
continue;
}
perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot::
MemoryNode::MemoryNodeEntry* proto_memory_node_entry =
memory_node->add_entries();
proto_memory_node_entry->set_name(entry.name);
switch (entry.entry_type) {
case Entry::EntryType::kUint64:
proto_memory_node_entry->set_value_uint64(entry.value_uint64);
break;
case Entry::EntryType::kString:
proto_memory_node_entry->set_value_string(entry.value_string);
break;
}
if (entry.units == "kBytes") {
proto_memory_node_entry->set_units(
perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::
MemoryNode::MemoryNodeEntry::BYTES);
} else if (entry.units == "kObjects") {
proto_memory_node_entry->set_units(
perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::
MemoryNode::MemoryNodeEntry::COUNT);
} else {
proto_memory_node_entry->set_units(
perfetto::protos::pbzero::MemoryTrackerSnapshot::ProcessSnapshot::
MemoryNode::MemoryNodeEntry::UNSPECIFIED);
}
}
}
uint64_t MemoryAllocatorDump::GetSizeInternal() const { uint64_t MemoryAllocatorDump::GetSizeInternal() const {
if (cached_size_.has_value()) if (cached_size_.has_value())
return *cached_size_; return *cached_size_;
......
...@@ -21,6 +21,14 @@ ...@@ -21,6 +21,14 @@
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "base/values.h" #include "base/values.h"
namespace perfetto {
namespace protos {
namespace pbzero {
class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode;
}
} // namespace protos
} // namespace perfetto
namespace base { namespace base {
namespace trace_event { namespace trace_event {
...@@ -101,6 +109,10 @@ class BASE_EXPORT MemoryAllocatorDump { ...@@ -101,6 +109,10 @@ class BASE_EXPORT MemoryAllocatorDump {
// Called at trace generation time to populate the TracedValue. // Called at trace generation time to populate the TracedValue.
void AsValueInto(TracedValue* value) const; void AsValueInto(TracedValue* value) const;
void AsProtoInto(
perfetto::protos::pbzero::
MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode* memory_node) const;
// Get the size for this dump. // Get the size for this dump.
// The size is the value set with AddScalar(kNameSize, kUnitsBytes, size); // The size is the value set with AddScalar(kNameSize, kUnitsBytes, size);
// TODO(hjd): this should return an Optional<uint64_t>. // TODO(hjd): this should return an Optional<uint64_t>.
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "base/trace_event/traced_value.h" #include "base/trace_event/traced_value.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
#if defined(OS_IOS) #if defined(OS_IOS)
#include <mach/vm_page_size.h> #include <mach/vm_page_size.h>
...@@ -33,6 +35,9 @@ ...@@ -33,6 +35,9 @@
#include <Psapi.h> #include <Psapi.h>
#endif #endif
using ProcessSnapshot =
::perfetto::protos::pbzero::MemoryTrackerSnapshot_ProcessSnapshot;
namespace base { namespace base {
namespace trace_event { namespace trace_event {
...@@ -387,6 +392,28 @@ void ProcessMemoryDump::SerializeAllocatorDumpsInto(TracedValue* value) const { ...@@ -387,6 +392,28 @@ void ProcessMemoryDump::SerializeAllocatorDumpsInto(TracedValue* value) const {
value->EndArray(); value->EndArray();
} }
void ProcessMemoryDump::SerializeAllocatorDumpsInto(
perfetto::protos::pbzero::MemoryTrackerSnapshot* memory_snapshot) const {
ProcessSnapshot* process_snapshot =
memory_snapshot->add_process_memory_dumps();
for (const auto& allocator_dump_it : allocator_dumps_) {
ProcessSnapshot::MemoryNode* memory_node =
process_snapshot->add_allocator_dumps();
allocator_dump_it.second->AsProtoInto(memory_node);
}
for (const auto& it : allocator_dumps_edges_) {
const MemoryAllocatorDumpEdge& edge = it.second;
ProcessSnapshot::MemoryEdge* memory_edge =
process_snapshot->add_memory_edges();
memory_edge->set_source_id(edge.source.ToUint64());
memory_edge->set_target_id(edge.target.ToUint64());
memory_edge->set_importance(edge.importance);
}
}
void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
const MemoryAllocatorDumpGuid& target, const MemoryAllocatorDumpGuid& target,
int importance) { int importance) {
......
...@@ -26,6 +26,14 @@ ...@@ -26,6 +26,14 @@
#define COUNT_RESIDENT_BYTES_SUPPORTED #define COUNT_RESIDENT_BYTES_SUPPORTED
#endif #endif
namespace perfetto {
namespace protos {
namespace pbzero {
class MemoryTrackerSnapshot;
}
} // namespace protos
} // namespace perfetto
namespace base { namespace base {
class UnguessableToken; class UnguessableToken;
...@@ -224,6 +232,9 @@ class BASE_EXPORT ProcessMemoryDump { ...@@ -224,6 +232,9 @@ class BASE_EXPORT ProcessMemoryDump {
// dumps. // dumps.
void SerializeAllocatorDumpsInto(TracedValue* value) const; void SerializeAllocatorDumpsInto(TracedValue* value) const;
void SerializeAllocatorDumpsInto(
perfetto::protos::pbzero::MemoryTrackerSnapshot* memory_snapshot) const;
const MemoryDumpArgs& dump_args() const { return dump_args_; } const MemoryDumpArgs& dump_args() const { return dump_args_; }
private: private:
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/values.h" #include "base/values.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
namespace heap_profiling { namespace heap_profiling {
namespace { namespace {
...@@ -125,7 +125,7 @@ base::Value BuildAllocatorsSummary(const AllocationMap& allocations) { ...@@ -125,7 +125,7 @@ base::Value BuildAllocatorsSummary(const AllocationMap& allocations) {
base::Value BuildMemoryMaps(const ExportParams& params) { base::Value BuildMemoryMaps(const ExportParams& params) {
base::trace_event::TracedValueJSON traced_value; base::trace_event::TracedValueJSON traced_value;
memory_instrumentation::TracingObserver::MemoryMapsAsValueInto( memory_instrumentation::TracingObserverTracedValue::MemoryMapsAsValueInto(
params.maps, &traced_value, params.strip_path_from_mapped_files); params.maps, &traced_value, params.strip_path_from_mapped_files);
return traced_value.ToBaseValue()->Clone(); return traced_value.ToBaseValue()->Clone();
} }
......
...@@ -54,6 +54,7 @@ source_set("tests") { ...@@ -54,6 +54,7 @@ source_set("tests") {
"public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits_unittest.cc", "public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits_unittest.cc",
"public/cpp/memory_instrumentation/os_metrics_unittest.cc", "public/cpp/memory_instrumentation/os_metrics_unittest.cc",
"public/cpp/memory_instrumentation/tracing_integration_unittest.cc", "public/cpp/memory_instrumentation/tracing_integration_unittest.cc",
"public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc",
] ]
deps = [ deps = [
...@@ -64,6 +65,7 @@ source_set("tests") { ...@@ -64,6 +65,7 @@ source_set("tests") {
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/resource_coordinator/public/cpp/memory_instrumentation:memory_instrumentation", "//services/resource_coordinator/public/cpp/memory_instrumentation:memory_instrumentation",
"//services/tracing:tests",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
] ]
......
...@@ -3,4 +3,5 @@ include_rules = [ ...@@ -3,4 +3,5 @@ include_rules = [
"+third_party/perfetto", "+third_party/perfetto",
"+third_party/smhasher", "+third_party/smhasher",
"+services/metrics/public", "+services/metrics/public",
"+services/tracing/public/cpp",
] ]
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h" #include "services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h"
#include "services/resource_coordinator/memory_instrumentation/switches.h" #include "services/resource_coordinator/memory_instrumentation/switches.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
...@@ -62,14 +64,21 @@ class StringWrapper : public base::trace_event::ConvertableToTraceFormat { ...@@ -62,14 +64,21 @@ class StringWrapper : public base::trace_event::ConvertableToTraceFormat {
CoordinatorImpl::CoordinatorImpl() CoordinatorImpl::CoordinatorImpl()
: next_dump_id_(0), : next_dump_id_(0),
client_process_timeout_(base::TimeDelta::FromSeconds(15)) { client_process_timeout_(base::TimeDelta::FromSeconds(15)),
use_proto_writer_(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMemoryTrackingProtoWriter)) {
DCHECK(!g_coordinator_impl); DCHECK(!g_coordinator_impl);
g_coordinator_impl = this; g_coordinator_impl = this;
base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id(
mojom::kServiceTracingProcessId); mojom::kServiceTracingProcessId);
tracing_observer_ = std::make_unique<TracingObserver>( if (use_proto_writer_) {
base::trace_event::TraceLog::GetInstance(), nullptr); tracing_observer_ = std::make_unique<TracingObserverProto>(
base::trace_event::TraceLog::GetInstance(), nullptr);
} else {
tracing_observer_ = std::make_unique<TracingObserverTracedValue>(
base::trace_event::TraceLog::GetInstance(), nullptr);
}
} }
CoordinatorImpl::~CoordinatorImpl() { CoordinatorImpl::~CoordinatorImpl() {
...@@ -567,7 +576,8 @@ void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { ...@@ -567,7 +576,8 @@ void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() {
return; return;
} }
QueuedRequestDispatcher::Finalize(request, tracing_observer_.get()); QueuedRequestDispatcher::Finalize(request, tracing_observer_.get(),
use_proto_writer_);
queued_memory_dump_requests_.pop_front(); queued_memory_dump_requests_.pop_front();
request = nullptr; request = nullptr;
......
...@@ -190,6 +190,8 @@ class CoordinatorImpl : public mojom::CoordinatorController, ...@@ -190,6 +190,8 @@ class CoordinatorImpl : public mojom::CoordinatorController,
mojo::Receiver<mojom::HeapProfilerHelper> heap_profiler_helper_receiver_{ mojo::Receiver<mojom::HeapProfilerHelper> heap_profiler_helper_receiver_{
this}; this};
const bool use_proto_writer_;
THREAD_CHECKER(thread_checker_); THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<CoordinatorImpl> weak_ptr_factory_{this}; base::WeakPtrFactory<CoordinatorImpl> weak_ptr_factory_{this};
......
...@@ -19,7 +19,12 @@ ...@@ -19,7 +19,12 @@
#include "services/resource_coordinator/memory_instrumentation/aggregate_metrics_processor.h" #include "services/resource_coordinator/memory_instrumentation/aggregate_metrics_processor.h"
#include "services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h" #include "services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h"
#include "services/resource_coordinator/memory_instrumentation/switches.h" #include "services/resource_coordinator/memory_instrumentation/switches.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h" #include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
#if defined(OS_MAC) #if defined(OS_MAC)
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
...@@ -382,7 +387,8 @@ QueuedRequestDispatcher::FinalizeVmRegionRequest( ...@@ -382,7 +387,8 @@ QueuedRequestDispatcher::FinalizeVmRegionRequest(
} }
void QueuedRequestDispatcher::Finalize(QueuedRequest* request, void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
TracingObserver* tracing_observer) { TracingObserver* tracing_observer,
bool use_proto_writer) {
DCHECK(request->dump_in_progress); DCHECK(request->dump_in_progress);
DCHECK(request->pending_responses.empty()); DCHECK(request->pending_responses.empty());
...@@ -438,7 +444,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, ...@@ -438,7 +444,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
pid_to_os_dump[original_pid] = kv.second.get(); pid_to_os_dump[original_pid] = kv.second.get();
} }
#endif #endif
} // for (response : request->responses) }
MemoryDumpMapConverter converter; MemoryDumpMapConverter converter;
perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap perfettoNodeMap = perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap perfettoNodeMap =
...@@ -446,6 +452,8 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, ...@@ -446,6 +452,8 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
// Generate the global memory graph from the map of pids to dumps, removing // Generate the global memory graph from the map of pids to dumps, removing
// weak nodes. // weak nodes.
// TODO (crbug.com/1112671): We should avoid graph processing once we moved
// the shared footprint computation to perfetto.
std::unique_ptr<GlobalNodeGraph> global_graph = std::unique_ptr<GlobalNodeGraph> global_graph =
GraphProcessor::CreateMemoryGraph(perfettoNodeMap); GraphProcessor::CreateMemoryGraph(perfettoNodeMap);
GraphProcessor::RemoveWeakNodesFromGraph(global_graph.get()); GraphProcessor::RemoveWeakNodesFromGraph(global_graph.get());
...@@ -511,8 +519,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, ...@@ -511,8 +519,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
if (request->args.add_to_trace) { if (request->args.add_to_trace) {
if (raw_os_dump) { if (raw_os_dump) {
bool trace_os_success = tracing_observer->AddOsDumpToTraceIfEnabled( bool trace_os_success = tracing_observer->AddOsDumpToTraceIfEnabled(
request->GetRequestArgs(), pid, os_dump.get(), request->GetRequestArgs(), pid, *os_dump, raw_os_dump->memory_maps);
&raw_os_dump->memory_maps);
if (!trace_os_success) if (!trace_os_success)
request->failed_memory_dump_count++; request->failed_memory_dump_count++;
} }
...@@ -520,7 +527,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request, ...@@ -520,7 +527,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
if (raw_chrome_dump) { if (raw_chrome_dump) {
bool trace_chrome_success = AddChromeMemoryDumpToTrace( bool trace_chrome_success = AddChromeMemoryDumpToTrace(
request->GetRequestArgs(), pid, *raw_chrome_dump, *global_graph, request->GetRequestArgs(), pid, *raw_chrome_dump, *global_graph,
pid_to_process_type, tracing_observer); pid_to_process_type, tracing_observer, use_proto_writer);
if (!trace_chrome_success) if (!trace_chrome_success)
request->failed_memory_dump_count++; request->failed_memory_dump_count++;
} }
...@@ -602,7 +609,8 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace( ...@@ -602,7 +609,8 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace(
const base::trace_event::ProcessMemoryDump& raw_chrome_dump, const base::trace_event::ProcessMemoryDump& raw_chrome_dump,
const GlobalNodeGraph& global_graph, const GlobalNodeGraph& global_graph,
const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type, const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type,
TracingObserver* tracing_observer) { TracingObserver* tracing_observer,
bool use_proto_writer) {
bool is_chrome_tracing_enabled = bool is_chrome_tracing_enabled =
base::CommandLine::ForCurrentProcess()->HasSwitch( base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableChromeTracingComputation); switches::kEnableChromeTracingComputation);
...@@ -613,6 +621,11 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace( ...@@ -613,6 +621,11 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace(
if (!tracing_observer->ShouldAddToTrace(args)) if (!tracing_observer->ShouldAddToTrace(args))
return false; return false;
if (use_proto_writer) {
return tracing_observer->AddChromeDumpToTraceIfEnabled(args, pid,
&raw_chrome_dump);
}
const GlobalNodeGraph::Process& process = const GlobalNodeGraph::Process& process =
*global_graph.process_node_graphs().find(pid)->second; *global_graph.process_node_graphs().find(pid)->second;
...@@ -623,7 +636,7 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace( ...@@ -623,7 +636,7 @@ bool QueuedRequestDispatcher::AddChromeMemoryDumpToTrace(
} else { } else {
traced_value = GetChromeDumpTracedValue(process); traced_value = GetChromeDumpTracedValue(process);
} }
tracing_observer->AddToTrace(args, pid, std::move(traced_value)); TracingObserverTracedValue::AddToTrace(args, pid, std::move(traced_value));
return true; return true;
} }
......
...@@ -62,7 +62,8 @@ class QueuedRequestDispatcher { ...@@ -62,7 +62,8 @@ class QueuedRequestDispatcher {
// dispatching to the appropriate callback. Also adds to tracing using // dispatching to the appropriate callback. Also adds to tracing using
// |tracing_observer| if the |request| requires it. // |tracing_observer| if the |request| requires it.
static void Finalize(QueuedRequest* request, static void Finalize(QueuedRequest* request,
TracingObserver* tracing_observer); TracingObserver* tracing_observer,
bool use_proto_writer);
static void SetUpAndDispatchVmRegionRequest( static void SetUpAndDispatchVmRegionRequest(
QueuedVmRegionRequest* request, QueuedVmRegionRequest* request,
...@@ -78,7 +79,8 @@ class QueuedRequestDispatcher { ...@@ -78,7 +79,8 @@ class QueuedRequestDispatcher {
const base::trace_event::ProcessMemoryDump& raw_chrome_dump, const base::trace_event::ProcessMemoryDump& raw_chrome_dump,
const perfetto::trace_processor::GlobalNodeGraph& global_graph, const perfetto::trace_processor::GlobalNodeGraph& global_graph,
const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type, const std::map<base::ProcessId, mojom::ProcessType>& pid_to_process_type,
TracingObserver* tracing_observer); TracingObserver* tracing_observer,
bool use_proto_writer);
}; };
} // namespace memory_instrumentation } // namespace memory_instrumentation
......
...@@ -10,6 +10,7 @@ namespace switches { ...@@ -10,6 +10,7 @@ namespace switches {
// Enable the tracing service. // Enable the tracing service.
const char kEnableChromeTracingComputation[] = const char kEnableChromeTracingComputation[] =
"enable-chrome-tracing-computation"; "enable-chrome-tracing-computation";
const char kUseMemoryTrackingProtoWriter[] = "use-memory-tracking-proto-writer";
} // namespace switches } // namespace switches
} // namespace memory_instrumentation } // namespace memory_instrumentation
\ No newline at end of file
...@@ -11,8 +11,9 @@ namespace switches { ...@@ -11,8 +11,9 @@ namespace switches {
// All switches in alphabetical order. The switches should be documented // All switches in alphabetical order. The switches should be documented
// alongside the definition of their values in the .cc file. // alongside the definition of their values in the .cc file.
extern const char kEnableChromeTracingComputation[]; extern const char kEnableChromeTracingComputation[];
extern const char kUseMemoryTrackingProtoWriter[];
} // namespace switches } // namespace switches
} // namespace memory_instrumentation } // namespace memory_instrumentation
#endif // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_SWITCHES_H_ #endif // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_SWITCHES_H_
\ No newline at end of file
...@@ -24,6 +24,10 @@ component("memory_instrumentation") { ...@@ -24,6 +24,10 @@ component("memory_instrumentation") {
"os_metrics_win.cc", "os_metrics_win.cc",
"tracing_observer.cc", "tracing_observer.cc",
"tracing_observer.h", "tracing_observer.h",
"tracing_observer_proto.cc",
"tracing_observer_proto.h",
"tracing_observer_traced_value.cc",
"tracing_observer_traced_value.h",
] ]
if (is_android) { if (is_android) {
...@@ -48,6 +52,7 @@ component("memory_instrumentation") { ...@@ -48,6 +52,7 @@ component("memory_instrumentation") {
"//base", "//base",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/resource_coordinator/public/mojom", "//services/resource_coordinator/public/mojom",
"//services/tracing/public/cpp",
] ]
} }
......
...@@ -96,8 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) ...@@ -96,8 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
mojo::Remote<mojom::Coordinator> coordinator_; mojo::Remote<mojom::Coordinator> coordinator_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// TODO(ssid): This should be moved to coordinator instead of clients once we // TODO(crbug.com/728199): The observer is only used to setup and tear down
// have the whole chrome dumps sent via mojo, crbug.com/728199. // MemoryDumpManager in each process. Setting up MemoryDumpManager should
// be moved away from TracingObserver.
std::unique_ptr<TracingObserver> tracing_observer_; std::unique_ptr<TracingObserver> tracing_observer_;
DISALLOW_COPY_AND_ASSIGN(ClientProcessImpl); DISALLOW_COPY_AND_ASSIGN(ClientProcessImpl);
......
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -25,29 +25,6 @@ bool IsMemoryInfraTracingEnabled() { ...@@ -25,29 +25,6 @@ bool IsMemoryInfraTracingEnabled() {
return enabled; return enabled;
} }
void OsDumpAsValueInto(TracedValue* value, const mojom::OSMemDump& os_dump) {
value->SetString(
"private_footprint_bytes",
base::StringPrintf(
"%" PRIx64,
static_cast<uint64_t>(os_dump.private_footprint_kb) * 1024));
value->SetString(
"peak_resident_set_size",
base::StringPrintf(
"%" PRIx64,
static_cast<uint64_t>(os_dump.peak_resident_set_kb) * 1024));
value->SetBoolean("is_peak_rss_resettable", os_dump.is_peak_rss_resettable);
}
std::string ApplyPathFiltering(const std::string& file,
bool is_argument_filtering_enabled) {
if (is_argument_filtering_enabled) {
base::FilePath::StringType path(file.begin(), file.end());
return base::FilePath(path).BaseName().AsUTF8Unsafe();
}
return file;
}
} // namespace } // namespace
TracingObserver::TracingObserver( TracingObserver::TracingObserver(
...@@ -97,6 +74,21 @@ void TracingObserver::OnTraceLogDisabled() { ...@@ -97,6 +74,21 @@ void TracingObserver::OnTraceLogDisabled() {
memory_dump_config_.reset(); memory_dump_config_.reset();
} }
bool TracingObserver::AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId pid,
const base::trace_event::ProcessMemoryDump*) {
return false;
}
bool TracingObserver::AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const mojom::OSMemDump& os_dump,
const std::vector<mojom::VmRegionPtr>& memory_maps) {
return false;
}
bool TracingObserver::ShouldAddToTrace( bool TracingObserver::ShouldAddToTrace(
const base::trace_event::MemoryDumpRequestArgs& args) { const base::trace_event::MemoryDumpRequestArgs& args) {
// If tracing has been disabled early out to avoid the cost of serializing the // If tracing has been disabled early out to avoid the cost of serializing the
...@@ -110,125 +102,15 @@ bool TracingObserver::ShouldAddToTrace( ...@@ -110,125 +102,15 @@ bool TracingObserver::ShouldAddToTrace(
return true; return true;
} }
void TracingObserver::AddToTrace(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
std::unique_ptr<TracedValue> traced_value) {
CHECK_NE(base::trace_event::MemoryDumpType::SUMMARY_ONLY, args.dump_type);
traced_value->SetString(
"level_of_detail",
base::trace_event::MemoryDumpLevelOfDetailToString(args.level_of_detail));
const uint64_t dump_guid = args.dump_guid;
const char* const event_name =
base::trace_event::MemoryDumpTypeToString(args.dump_type);
base::trace_event::TraceArguments trace_args("dumps",
std::move(traced_value));
TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
TRACE_EVENT_PHASE_MEMORY_DUMP,
base::trace_event::TraceLog::GetCategoryGroupEnabled(
base::trace_event::MemoryDumpManager::kTraceCategory),
event_name, trace_event_internal::kGlobalScope, dump_guid, pid,
&trace_args, TRACE_EVENT_FLAG_HAS_ID);
}
bool TracingObserver::AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const ProcessMemoryDump* process_memory_dump) {
if (!ShouldAddToTrace(args))
return false;
std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
process_memory_dump->SerializeAllocatorDumpsInto(traced_value.get());
AddToTrace(args, pid, std::move(traced_value));
return true;
}
bool TracingObserver::AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const mojom::OSMemDump* os_dump,
const std::vector<mojom::VmRegionPtr>* memory_maps) {
if (!ShouldAddToTrace(args))
return false;
std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
traced_value->BeginDictionary("process_totals");
OsDumpAsValueInto(traced_value.get(), *os_dump);
traced_value->EndDictionary();
if (memory_maps->size()) {
traced_value->BeginDictionary("process_mmaps");
MemoryMapsAsValueInto(*memory_maps, traced_value.get(), false);
traced_value->EndDictionary();
}
AddToTrace(args, pid, std::move(traced_value));
return true;
}
// static // static
void TracingObserver::MemoryMapsAsValueInto( std::string TracingObserver::ApplyPathFiltering(
const std::vector<mojom::VmRegionPtr>& memory_maps, const std::string& file,
TracedValue* value,
bool is_argument_filtering_enabled) { bool is_argument_filtering_enabled) {
static const char kHexFmt[] = "%" PRIx64; if (is_argument_filtering_enabled) {
base::FilePath::StringType path(file.begin(), file.end());
// Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields. return base::FilePath(path).BaseName().AsUTF8Unsafe();
value->BeginArray("vm_regions");
for (const auto& region : memory_maps) {
value->BeginDictionary();
value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address));
value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes));
if (region->module_timestamp)
value->SetString("ts",
base::StringPrintf(kHexFmt, region->module_timestamp));
if (!region->module_debugid.empty())
value->SetString("id", region->module_debugid);
if (!region->module_debug_path.empty()) {
value->SetString("df", ApplyPathFiltering(region->module_debug_path,
is_argument_filtering_enabled));
}
value->SetInteger("pf", region->protection_flags);
// The module path will be the basename when argument filtering is
// activated. The whitelisting implemented for filtering string values
// doesn't allow rewriting. Therefore, a different path is produced here
// when argument filtering is activated.
value->SetString("mf", ApplyPathFiltering(region->mapped_file,
is_argument_filtering_enabled));
// The following stats are only well defined on Linux-derived OSes.
#if !defined(OS_MAC) && !defined(OS_WIN)
value->BeginDictionary("bs"); // byte stats
value->SetString(
"pss",
base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident));
value->SetString(
"pd",
base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident));
value->SetString(
"pc",
base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident));
value->SetString(
"sd",
base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident));
value->SetString(
"sc",
base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident));
value->SetString("sw",
base::StringPrintf(kHexFmt, region->byte_stats_swapped));
value->EndDictionary();
#endif
value->EndDictionary();
} }
value->EndArray(); return file;
} }
bool TracingObserver::IsDumpModeAllowed( bool TracingObserver::IsDumpModeAllowed(
......
...@@ -2,14 +2,15 @@ ...@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H #ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H #define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_
#include "base/component_export.h" #include "base/component_export.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
namespace memory_instrumentation { namespace memory_instrumentation {
...@@ -27,27 +28,24 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) ...@@ -27,27 +28,24 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
void OnTraceLogEnabled() override; void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override; void OnTraceLogDisabled() override;
bool AddChromeDumpToTraceIfEnabled( virtual bool AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&, const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId pid, const base::ProcessId pid,
const base::trace_event::ProcessMemoryDump*); const base::trace_event::ProcessMemoryDump*);
bool AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId,
const mojom::OSMemDump*,
const std::vector<mojom::VmRegionPtr>*);
static void MemoryMapsAsValueInto( virtual bool AddOsDumpToTraceIfEnabled(
const std::vector<mojom::VmRegionPtr>& memory_maps, const base::trace_event::MemoryDumpRequestArgs& args,
base::trace_event::TracedValue* value, const base::ProcessId pid,
bool is_argument_filtering_enabled); const mojom::OSMemDump& os_dump,
const std::vector<mojom::VmRegionPtr>& memory_maps);
// TODO(lalitm): make these private again after TracingObserver is moved // TODO(lalitm): make these private again after TracingObserver is moved
// to private space. // to private space.
bool ShouldAddToTrace(const base::trace_event::MemoryDumpRequestArgs&); bool ShouldAddToTrace(const base::trace_event::MemoryDumpRequestArgs&);
void AddToTrace(const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId, protected:
std::unique_ptr<base::trace_event::TracedValue>); static std::string ApplyPathFiltering(const std::string& file,
bool is_argument_filtering_enabled);
private: private:
// Returns true if the dump mode is allowed for current tracing session. // Returns true if the dump mode is allowed for current tracing session.
...@@ -63,4 +61,4 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) ...@@ -63,4 +61,4 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
} // namespace memory_instrumentation } // namespace memory_instrumentation
#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H #endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/profiling/smaps.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/ps/process_stats.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
namespace memory_instrumentation {
using base::trace_event::ProcessMemoryDump;
namespace {
void OsDumpAsProtoInto(perfetto::protos::pbzero::ProcessStats::Process* process,
const mojom::OSMemDump& os_dump) {
process->set_chrome_private_footprint_kb(os_dump.private_footprint_kb);
process->set_chrome_peak_resident_set_kb(os_dump.peak_resident_set_kb);
process->set_is_peak_rss_resettable(os_dump.is_peak_rss_resettable);
}
perfetto::protos::pbzero::MemoryTrackerSnapshot::LevelOfDetail
MemoryDumpLevelOfDetailToProto(
const base::trace_event::MemoryDumpLevelOfDetail& level_of_detail) {
switch (level_of_detail) {
case base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND:
return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_BACKGROUND;
case base::trace_event::MemoryDumpLevelOfDetail::LIGHT:
return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_LIGHT;
case base::trace_event::MemoryDumpLevelOfDetail::DETAILED:
return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_FULL;
}
NOTREACHED();
return perfetto::protos::pbzero::MemoryTrackerSnapshot::DETAIL_BACKGROUND;
}
} // namespace
TracingObserverProto::TracingObserverProto(
base::trace_event::TraceLog* trace_log,
base::trace_event::MemoryDumpManager* memory_dump_manager)
: TracingObserver(trace_log, memory_dump_manager),
tracing::PerfettoTracedProcess::DataSourceBase(
tracing::mojom::kMemoryInstrumentationDataSourceName) {
tracing::PerfettoTracedProcess::Get()->AddDataSource(this);
}
TracingObserverProto::~TracingObserverProto() = default;
bool TracingObserverProto::AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const ProcessMemoryDump* process_memory_dump) {
if (!ShouldAddToTrace(args))
return false;
base::AutoLock lock(producer_lock_);
if (!trace_writer_)
return false;
perfetto::TraceWriter::TracePacketHandle handle =
trace_writer_->NewTracePacket();
perfetto::protos::pbzero::MemoryTrackerSnapshot* memory_snapshot =
handle->set_memory_tracker_snapshot();
memory_snapshot->set_level_of_detail(
MemoryDumpLevelOfDetailToProto(args.level_of_detail));
process_memory_dump->SerializeAllocatorDumpsInto(memory_snapshot);
return true;
}
bool TracingObserverProto::AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const mojom::OSMemDump& os_dump,
const std::vector<mojom::VmRegionPtr>& memory_maps) {
if (!ShouldAddToTrace(args))
return false;
base::AutoLock lock(producer_lock_);
if (!trace_writer_)
return false;
perfetto::TraceWriter::TracePacketHandle process_stats_packet =
trace_writer_->NewTracePacket();
perfetto::protos::pbzero::ProcessStats* process_stats =
process_stats_packet->set_process_stats();
perfetto::protos::pbzero::ProcessStats::Process* process =
process_stats->add_processes();
OsDumpAsProtoInto(process, os_dump);
process_stats_packet->Finalize();
if (memory_maps.size()) {
perfetto::TraceWriter::TracePacketHandle smaps_packet =
trace_writer_->NewTracePacket();
perfetto::protos::pbzero::SmapsPacket* smaps =
smaps_packet->set_smaps_packet();
MemoryMapsAsProtoInto(memory_maps, smaps, false);
smaps_packet->Finalize();
}
return true;
}
void TracingObserverProto::StartTracing(
tracing::PerfettoProducer* producer,
const perfetto::DataSourceConfig& data_source_config) {
base::AutoLock lock(producer_lock_);
producer_ = producer;
// We rely on concurrent setup of TraceLog categories by the
// TraceEventDataSource so don't look at the trace config ourselves.
trace_writer_ =
producer->CreateTraceWriter(data_source_config.target_buffer());
}
void TracingObserverProto::StopTracing(
base::OnceClosure stop_complete_callback) {
// Scope to avoid reentrancy in case from the stop callback.
{
base::AutoLock lock(producer_lock_);
trace_writer_.reset();
producer_ = nullptr;
}
if (stop_complete_callback) {
std::move(stop_complete_callback).Run();
}
}
void TracingObserverProto::Flush(
base::RepeatingClosure flush_complete_callback) {}
void TracingObserverProto::MemoryMapsAsProtoInto(
const std::vector<mojom::VmRegionPtr>& memory_maps,
perfetto::protos::pbzero::SmapsPacket* smaps,
bool is_argument_filtering_enabled) {
for (const auto& region : memory_maps) {
perfetto::protos::pbzero::SmapsEntry* entry = smaps->add_entries();
entry->set_start_address(region->start_address);
entry->set_size_kb(region->size_in_bytes / 1024);
if (region->module_timestamp)
entry->set_module_timestamp(region->module_timestamp);
if (!region->module_debugid.empty())
entry->set_module_debugid(region->module_debugid);
if (!region->module_debug_path.empty()) {
entry->set_module_debug_path(ApplyPathFiltering(
region->module_debug_path, is_argument_filtering_enabled));
}
entry->set_protection_flags(region->protection_flags);
entry->set_file_name(
ApplyPathFiltering(region->mapped_file, is_argument_filtering_enabled));
// The following stats are only well defined on Linux-derived OSes.
#if !defined(OS_MAC) && !defined(OS_WIN)
entry->set_proportional_resident_kb(
region->byte_stats_proportional_resident / 1024);
entry->set_private_dirty_kb(region->byte_stats_private_dirty_resident /
1024);
entry->set_private_clean_resident_kb(
region->byte_stats_private_clean_resident / 1024);
entry->set_shared_dirty_resident_kb(
region->byte_stats_shared_dirty_resident / 1024);
entry->set_shared_clean_resident_kb(
region->byte_stats_shared_clean_resident / 1024);
entry->set_swap_kb(region->byte_stats_swapped / 1024);
#endif
}
}
} // namespace memory_instrumentation
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_
#include "base/component_export.h"
#include "base/macros.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
namespace perfetto {
namespace protos {
namespace pbzero {
class SmapsPacket;
}
} // namespace protos
} // namespace perfetto
namespace memory_instrumentation {
// Version of TracingObserver that serializes the dump into a proto TracePacket.
class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
TracingObserverProto
: public TracingObserver,
public tracing::PerfettoTracedProcess::DataSourceBase {
public:
TracingObserverProto(base::trace_event::TraceLog*,
base::trace_event::MemoryDumpManager*);
~TracingObserverProto() override;
bool AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId pid,
const base::trace_event::ProcessMemoryDump*) override;
bool AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId,
const mojom::OSMemDump&,
const std::vector<mojom::VmRegionPtr>&) override;
void StartTracing(
tracing::PerfettoProducer* producer,
const perfetto::DataSourceConfig& data_source_config) override;
void StopTracing(
base::OnceClosure stop_complete_callback = base::OnceClosure()) override;
void Flush(base::RepeatingClosure flush_complete_callback) override;
static void MemoryMapsAsProtoInto(
const std::vector<mojom::VmRegionPtr>& memory_maps,
perfetto::protos::pbzero::SmapsPacket* smaps,
bool is_argument_filtering_enabled);
private:
std::unique_ptr<perfetto::TraceWriter> trace_writer_;
base::Lock producer_lock_;
DISALLOW_COPY_AND_ASSIGN(TracingObserverProto);
};
} // namespace memory_instrumentation
#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_PROTO_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
namespace memory_instrumentation {
using base::trace_event::ProcessMemoryDump;
using base::trace_event::TracedValue;
namespace {
void OsDumpAsValueInto(TracedValue* value, const mojom::OSMemDump& os_dump) {
value->SetString(
"private_footprint_bytes",
base::StringPrintf(
"%" PRIx64,
static_cast<uint64_t>(os_dump.private_footprint_kb) * 1024));
value->SetString(
"peak_resident_set_size",
base::StringPrintf(
"%" PRIx64,
static_cast<uint64_t>(os_dump.peak_resident_set_kb) * 1024));
value->SetBoolean("is_peak_rss_resettable", os_dump.is_peak_rss_resettable);
}
} // namespace
TracingObserverTracedValue::TracingObserverTracedValue(
base::trace_event::TraceLog* trace_log,
base::trace_event::MemoryDumpManager* memory_dump_manager)
: TracingObserver(trace_log, memory_dump_manager) {}
TracingObserverTracedValue::~TracingObserverTracedValue() = default;
// static
void TracingObserverTracedValue::AddToTrace(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
std::unique_ptr<TracedValue> traced_value) {
CHECK_NE(base::trace_event::MemoryDumpType::SUMMARY_ONLY, args.dump_type);
traced_value->SetString(
"level_of_detail",
base::trace_event::MemoryDumpLevelOfDetailToString(args.level_of_detail));
const uint64_t dump_guid = args.dump_guid;
const char* const event_name =
base::trace_event::MemoryDumpTypeToString(args.dump_type);
base::trace_event::TraceArguments trace_args("dumps",
std::move(traced_value));
TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
TRACE_EVENT_PHASE_MEMORY_DUMP,
base::trace_event::TraceLog::GetCategoryGroupEnabled(
base::trace_event::MemoryDumpManager::kTraceCategory),
event_name, trace_event_internal::kGlobalScope, dump_guid, pid,
&trace_args, TRACE_EVENT_FLAG_HAS_ID);
}
bool TracingObserverTracedValue::AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const ProcessMemoryDump* process_memory_dump) {
if (!ShouldAddToTrace(args))
return false;
std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
process_memory_dump->SerializeAllocatorDumpsInto(traced_value.get());
AddToTrace(args, pid, std::move(traced_value));
return true;
}
bool TracingObserverTracedValue::AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs& args,
const base::ProcessId pid,
const mojom::OSMemDump& os_dump,
const std::vector<mojom::VmRegionPtr>& memory_maps) {
if (!ShouldAddToTrace(args))
return false;
std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>();
traced_value->BeginDictionary("process_totals");
OsDumpAsValueInto(traced_value.get(), os_dump);
traced_value->EndDictionary();
if (memory_maps.size()) {
traced_value->BeginDictionary("process_mmaps");
MemoryMapsAsValueInto(memory_maps, traced_value.get(), false);
traced_value->EndDictionary();
}
AddToTrace(args, pid, std::move(traced_value));
return true;
}
// static
void TracingObserverTracedValue::MemoryMapsAsValueInto(
const std::vector<mojom::VmRegionPtr>& memory_maps,
TracedValue* value,
bool is_argument_filtering_enabled) {
static const char kHexFmt[] = "%" PRIx64;
// Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields.
value->BeginArray("vm_regions");
for (const auto& region : memory_maps) {
value->BeginDictionary();
value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address));
value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes));
if (region->module_timestamp)
value->SetString("ts",
base::StringPrintf(kHexFmt, region->module_timestamp));
if (!region->module_debugid.empty())
value->SetString("id", region->module_debugid);
if (!region->module_debug_path.empty()) {
value->SetString("df", ApplyPathFiltering(region->module_debug_path,
is_argument_filtering_enabled));
}
value->SetInteger("pf", region->protection_flags);
// The module path will be the basename when argument filtering is
// activated. The whitelisting implemented for filtering string values
// doesn't allow rewriting. Therefore, a different path is produced here
// when argument filtering is activated.
value->SetString("mf", ApplyPathFiltering(region->mapped_file,
is_argument_filtering_enabled));
// The following stats are only well defined on Linux-derived OSes.
#if !defined(OS_MAC) && !defined(OS_WIN)
value->BeginDictionary("bs"); // byte stats
value->SetString(
"pss",
base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident));
value->SetString(
"pd",
base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident));
value->SetString(
"pc",
base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident));
value->SetString(
"sd",
base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident));
value->SetString(
"sc",
base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident));
value->SetString("sw",
base::StringPrintf(kHexFmt, region->byte_stats_swapped));
value->EndDictionary();
#endif
value->EndDictionary();
}
value->EndArray();
}
} // namespace memory_instrumentation
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_
#include "base/component_export.h"
#include "base/macros.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
namespace memory_instrumentation {
// Version of TracingObserver that serialized the dump into a TracedValue
class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
TracingObserverTracedValue : public TracingObserver {
public:
TracingObserverTracedValue(base::trace_event::TraceLog*,
base::trace_event::MemoryDumpManager*);
~TracingObserverTracedValue() override;
bool AddChromeDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId pid,
const base::trace_event::ProcessMemoryDump*) override;
bool AddOsDumpToTraceIfEnabled(
const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId,
const mojom::OSMemDump&,
const std::vector<mojom::VmRegionPtr>&) override;
static void MemoryMapsAsValueInto(
const std::vector<mojom::VmRegionPtr>& memory_maps,
base::trace_event::TracedValue* value,
bool is_argument_filtering_enabled);
static void AddToTrace(const base::trace_event::MemoryDumpRequestArgs&,
const base::ProcessId,
std::unique_ptr<base::trace_event::TracedValue>);
DISALLOW_COPY_AND_ASSIGN(TracingObserverTracedValue);
};
} // namespace memory_instrumentation
#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_TRACING_OBSERVER_TRACED_VALUE_H_
...@@ -38,7 +38,11 @@ source_set("lib") { ...@@ -38,7 +38,11 @@ source_set("lib") {
"//base", "//base",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/tracing/public/cpp", "//services/tracing/public/cpp",
"//services/tracing/public/mojom:mojom",
"//third_party/perfetto:libperfetto", "//third_party/perfetto:libperfetto",
"//third_party/perfetto/include/perfetto/ext/trace_processor:export_json",
"//third_party/perfetto/include/perfetto/trace_processor:basic_types",
"//third_party/perfetto/include/perfetto/trace_processor:storage",
"//third_party/perfetto/protos/perfetto/config:lite", "//third_party/perfetto/protos/perfetto/config:lite",
] ]
} }
...@@ -116,6 +120,7 @@ source_set("tests") { ...@@ -116,6 +120,7 @@ source_set("tests") {
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/tracing/public/cpp:buildflags", "//services/tracing/public/cpp:buildflags",
"//services/tracing/public/cpp/background_tracing:unit_tests", "//services/tracing/public/cpp/background_tracing:unit_tests",
"//services/tracing/public/mojom:mojom",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
"//third_party/perfetto/include/perfetto/protozero:protozero", "//third_party/perfetto/include/perfetto/protozero:protozero",
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_config.h" #include "base/trace_event/trace_config.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -49,6 +50,17 @@ void AddDataSourceConfigs( ...@@ -49,6 +50,17 @@ void AddDataSourceConfigs(
perfetto::protos::gen::ChromeConfig::ClientPriority client_priority) { perfetto::protos::gen::ChromeConfig::ClientPriority client_priority) {
const std::string chrome_config_string = stripped_config.ToString(); const std::string chrome_config_string = stripped_config.ToString();
if (stripped_config.IsCategoryGroupEnabled(
base::trace_event::MemoryDumpManager::kTraceCategory)) {
DCHECK(source_names.empty() ||
source_names.count(
tracing::mojom::kMemoryInstrumentationDataSourceName));
AddDataSourceConfig(perfetto_config,
tracing::mojom::kMemoryInstrumentationDataSourceName,
chrome_config_string, privacy_filtering_enabled,
convert_to_legacy_json, client_priority);
}
// Capture actual trace events. // Capture actual trace events.
if (source_names.empty() || if (source_names.empty() ||
source_names.count(tracing::mojom::kTraceEventDataSourceName) == 1) { source_names.count(tracing::mojom::kTraceEventDataSourceName) == 1) {
......
...@@ -12,6 +12,7 @@ module tracing.mojom; ...@@ -12,6 +12,7 @@ module tracing.mojom;
// particular interest is PosixSystemProducer::ConnectSocket(). // particular interest is PosixSystemProducer::ConnectSocket().
const string kPerfettoProducerNamePrefix = "org.chromium-"; const string kPerfettoProducerNamePrefix = "org.chromium-";
const string kTraceEventDataSourceName = "org.chromium.trace_event"; const string kTraceEventDataSourceName = "org.chromium.trace_event";
const string kMemoryInstrumentationDataSourceName = "org.chromium.memory_instrumentation";
const string kMetaDataSourceName = "org.chromium.trace_metadata"; const string kMetaDataSourceName = "org.chromium.trace_metadata";
const string kSystemTraceDataSourceName = "org.chromium.trace_system"; const string kSystemTraceDataSourceName = "org.chromium.trace_system";
const string kArcTraceDataSourceName = "org.chromium.trace_arc"; const string kArcTraceDataSourceName = "org.chromium.trace_arc";
......
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