#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "chrome/browser/metrics/process_memory_metrics_emitter.h"
#include <set>
#include <string>
#include <string_view>
#include <utility>
#include "base/allocator/buildflags.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/page_size.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_metrics.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/tab_footprint_aggregator.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_switches.h"
#include "components/metrics/metrics_data_validation.h"
#include "components/performance_manager/public/graph/frame_node.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/graph_operations.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/graph/process_node.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "content/public/browser/audio_service_info.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "extensions/buildflags/buildflags.h"
#include "media/mojo/mojom/cdm_service.mojom.h"
#include "partition_alloc/buildflags.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/child_process_binding_types.h"
#include "base/android/meminfo_dump_provider.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "media/mojo/mojom/media_foundation_service.mojom.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_map.h"
#include "extensions/common/extension.h"
#endif
MemoryAllocatorDump;
GetPrivateFootprintHistogramName;
GlobalMemoryDump;
HistogramProcessType;
HistogramProcessTypeToString;
kMemoryHistogramPrefix;
Memory_Experimental;
namespace {
const char kEffectiveSize[] = …;
const char kSize[] = …;
const char kAllocatedObjectsSize[] = …;
#if BUILDFLAG(IS_CHROMEOS)
const char kNonExoSize[] = "non_exo_size";
#endif
constexpr int kKiB = …;
constexpr int kMiB = …;
struct MetricRange { … };
const MetricRange ImageSizeMetricRange = …;
enum class MetricSize { … };
enum class EmitTo { … };
struct Metric { … };
const Metric kAllocatorDumpNamesForMetrics[] = …;
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
const Metric kPartitionAllocAddressSpaceMetrics[] = …;
#endif
#define UMA_HISTOGRAM_LARGE_MEMORY_MB(name, sample) …
#define EXPERIMENTAL_UMA_PREFIX …
#define VERSION_SUFFIX_PERCENT …
#define VERSION_SUFFIX_NORMAL …
#define VERSION_SUFFIX_SMALL …
#define VERSION_SUFFIX_TINY …
#define VERSION_SUFFIX_CUSTOM …
void EmitProcessUkm(const Metric& item,
uint64_t value,
Memory_Experimental* builder) { … }
const char* MetricSizeToVersionSuffix(MetricSize size) { … }
void EmitProcessUma(HistogramProcessType process_type,
const Metric& item,
uint64_t value) { … }
void EmitPartitionAllocFragmentationStat(
const GlobalMemoryDump::ProcessDump& pmd,
HistogramProcessType process_type,
const char* dump_name,
const char* uma_name) { … }
void EmitPartitionAllocWastedStat(const GlobalMemoryDump::ProcessDump& pmd,
HistogramProcessType process_type,
const char* dump_name,
const char* uma_name) { … }
void EmitMallocStats(const GlobalMemoryDump::ProcessDump& pmd,
HistogramProcessType process_type,
const std::optional<base::TimeDelta>& uptime) { … }
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
void EmitPartitionAllocAddressSpaceStatVariants(
const Metric& metric,
const uint64_t metric_value,
HistogramProcessType process_type,
const std::optional<base::TimeDelta>& uptime) { … }
void EmitPartitionAllocAddressSpaceStats(
const GlobalMemoryDump::ProcessDump& pmd,
HistogramProcessType process_type,
const std::optional<base::TimeDelta>& uptime) { … }
#endif
void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd,
HistogramProcessType process_type,
const std::optional<base::TimeDelta>& uptime,
bool record_uma,
Memory_Experimental* builder) { … }
void EmitSummedGpuMemory(const GlobalMemoryDump::ProcessDump& pmd,
Memory_Experimental* builder,
bool record_uma) { … }
#if BUILDFLAG(IS_CHROMEOS)
void EmitGpuMemoryNonExo(const GlobalMemoryDump::ProcessDump& pmd,
bool record_uma) {
if (!record_uma) {
return;
}
Metric synthetic_metric = {
nullptr, "GpuMemoryNonExo", MetricSize::kLarge,
kSize, EmitTo::kSizeInUmaOnly, nullptr};
uint64_t total = 0;
total += pmd.GetMetric("gpu/shared_images", kNonExoSize).value_or(0);
total += pmd.GetMetric("skia/gpu_resources", kSize).value_or(0);
EmitProcessUma(HistogramProcessType::kGpu, synthetic_metric, total);
}
#endif
void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
ukm::SourceId ukm_source_id,
ukm::UkmRecorder* ukm_recorder,
const std::optional<base::TimeDelta>& uptime,
bool record_uma) { … }
void EmitRendererMemoryMetrics(
const GlobalMemoryDump::ProcessDump& pmd,
const ProcessMemoryMetricsEmitter::PageInfo* page_info,
ukm::UkmRecorder* ukm_recorder,
int number_of_extensions,
const std::optional<base::TimeDelta>& uptime,
bool record_uma) { … }
void EmitGpuMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
ukm::SourceId ukm_source_id,
ukm::UkmRecorder* ukm_recorder,
const std::optional<base::TimeDelta>& uptime,
bool record_uma) { … }
void EmitUtilityMemoryMetrics(HistogramProcessType ptype,
const GlobalMemoryDump::ProcessDump& pmd,
ukm::SourceId ukm_source_id,
ukm::UkmRecorder* ukm_recorder,
const std::optional<base::TimeDelta>& uptime,
bool record_uma) { … }
#if BUILDFLAG(IS_ANDROID)
std::optional<base::android::ChildBindingState>
GetAndroidRendererProcessBindingState(
memory_instrumentation::mojom::ProcessType process_type,
base::ProcessId pid) {
if (process_type != memory_instrumentation::mojom::ProcessType::RENDERER) {
return std::nullopt;
}
for (auto iter = content::RenderProcessHost::AllHostsIterator();
!iter.IsAtEnd(); iter.Advance()) {
if (!iter.GetCurrentValue()->GetProcess().IsValid())
continue;
if (iter.GetCurrentValue()->GetProcess().Pid() == pid) {
return iter.GetCurrentValue()->GetEffectiveChildBindingState();
}
}
return base::android::ChildBindingState::UNBOUND;
}
#endif
}
ProcessMemoryMetricsEmitter::ProcessMemoryMetricsEmitter()
: … { … }
ProcessMemoryMetricsEmitter::ProcessMemoryMetricsEmitter(
base::ProcessId pid_scope)
: … { … }
void ProcessMemoryMetricsEmitter::FetchAndEmitProcessMemoryMetrics() { … }
void ProcessMemoryMetricsEmitter::MarkServiceRequestsInProgress() { … }
ProcessMemoryMetricsEmitter::~ProcessMemoryMetricsEmitter() { … }
void ProcessMemoryMetricsEmitter::ReceivedMemoryDump(
bool success,
std::unique_ptr<GlobalMemoryDump> dump) { … }
void ProcessMemoryMetricsEmitter::ReceivedProcessInfos(
std::vector<ProcessInfo> process_infos) { … }
ukm::UkmRecorder* ProcessMemoryMetricsEmitter::GetUkmRecorder() { … }
int ProcessMemoryMetricsEmitter::GetNumberOfExtensions(base::ProcessId pid) { … }
std::optional<base::TimeDelta> ProcessMemoryMetricsEmitter::GetProcessUptime(
base::TimeTicks now,
base::ProcessId pid) { … }
void ProcessMemoryMetricsEmitter::CollateResults() { … }
namespace {
bool HostsMainFrame(const performance_manager::ProcessNode* process,
const performance_manager::PageNode* page) { … }
}
void ProcessMemoryMetricsEmitter::GetProcessToPageInfoMap(
GetProcessToPageInfoMapCallback callback,
performance_manager::Graph* graph) { … }
ProcessMemoryMetricsEmitter::ProcessInfo::ProcessInfo() = default;
ProcessMemoryMetricsEmitter::ProcessInfo::ProcessInfo(ProcessInfo&& other) =
default;
ProcessMemoryMetricsEmitter::ProcessInfo::~ProcessInfo() = default;
ProcessMemoryMetricsEmitter::ProcessInfo&
ProcessMemoryMetricsEmitter::ProcessInfo::operator=(const ProcessInfo& other) =
default;