• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
6 #define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
7 
8 #include "base/allocator/buildflags.h"
9 #include "base/base_export.h"
10 #include "base/functional/callback.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/memory/singleton.h"
13 #include "base/synchronization/lock.h"
14 #include "base/time/time.h"
15 #include "base/trace_event/memory_dump_provider.h"
16 #include "build/build_config.h"
17 #include "partition_alloc/buildflags.h"
18 
19 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
20 #include "partition_alloc/partition_stats.h"  // nogncheck
21 #endif
22 
23 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
24     BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
25 #define MALLOC_MEMORY_TRACING_SUPPORTED
26 #endif
27 
28 namespace base {
29 namespace trace_event {
30 
31 class MemoryAllocatorDump;
32 
33 // Dump provider which collects process-wide memory stats.
34 class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider {
35  public:
36   // Name of the allocated_objects dump. Use this to declare suballocator dumps
37   // from other dump providers.
38   static const char kAllocatedObjects[];
39 
40   static MallocDumpProvider* GetInstance();
41 
42   // The Extreme LUD is implemented in //components/gwp_asan, which //base
43   // cannot depend on. The following API allows an injection of stats-report
44   // function of the Extreme LUD.
45   struct ExtremeLUDStats {
46 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
47     // This default-constructs to be zero'ed.
48     partition_alloc::LightweightQuarantineStats lq_stats{0};
49 #endif
50     size_t capacity_in_bytes = 0;
51   };
52   struct ExtremeLUDStatsSet {
53     ExtremeLUDStats for_small_objects{};
54     ExtremeLUDStats for_large_objects{};
55   };
56 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
57   using ExtremeLUDGetStatsCallback = RepeatingCallback<ExtremeLUDStatsSet()>;
58   static void SetExtremeLUDGetStatsCallback(
59       ExtremeLUDGetStatsCallback callback);
60 #endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
61 
62   MallocDumpProvider(const MallocDumpProvider&) = delete;
63   MallocDumpProvider& operator=(const MallocDumpProvider&) = delete;
64 
65   // MemoryDumpProvider implementation.
66   bool OnMemoryDump(const MemoryDumpArgs& args,
67                     ProcessMemoryDump* pmd) override;
68 
69  private:
70   struct CumulativeEludStats {
71     size_t quarantined_bytes = 0;
72     size_t quarantined_count = 0;
73     size_t miss_count = 0;
74   };
75 
76   friend struct DefaultSingletonTraits<MallocDumpProvider>;
77 
78   MallocDumpProvider();
79   ~MallocDumpProvider() override;
80 
81   void ReportPerMinuteStats(uint64_t syscall_count,
82                             size_t cumulative_brp_quarantined_bytes,
83                             size_t cumulative_brp_quarantined_count,
84                             const ExtremeLUDStats& elud_stats_for_small_objects,
85                             const ExtremeLUDStats& elud_stats_for_large_objects,
86                             MemoryAllocatorDump* malloc_dump,
87                             MemoryAllocatorDump* partition_alloc_dump,
88                             MemoryAllocatorDump* elud_dump_for_small_objects,
89                             MemoryAllocatorDump* elud_dump_for_large_objects);
90 
91   bool emit_metrics_on_memory_dump_
92       GUARDED_BY(emit_metrics_on_memory_dump_lock_) = true;
93   base::Lock emit_metrics_on_memory_dump_lock_;
94 
95 #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
96   // Returns a reference to the injected stats-report function of the Extreme
97   // LUD. The returned callback is_null() if the Extreme LUD is not enabled.
98   static ExtremeLUDGetStatsCallback& GetExtremeLUDGetStatsCallback();
99   // To be accurate, this requires the dump provider to be created very early,
100   // which is the case. The alternative would be to drop the first data point,
101   // which is not desirable as early process activity is highly relevant.
102   base::TimeTicks last_memory_dump_time_ = base::TimeTicks::Now();
103   uint64_t last_syscall_count_ = 0;
104   size_t last_cumulative_brp_quarantined_bytes_ = 0;
105   size_t last_cumulative_brp_quarantined_count_ = 0;
106   CumulativeEludStats last_cumulative_elud_stats_for_small_objects_{0};
107   CumulativeEludStats last_cumulative_elud_stats_for_large_objects_{0};
108 #endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
109 };
110 
111 #if PA_BUILDFLAG(USE_PARTITION_ALLOC)
112 // This class is used to invert the dependency of PartitionAlloc on the
113 // PartitionAllocMemoryDumpProvider. This implements an interface that will
114 // be called with memory statistics for each bucket in the allocator.
115 class BASE_EXPORT MemoryDumpPartitionStatsDumper final
116     : public partition_alloc::PartitionStatsDumper {
117  public:
118   MemoryDumpPartitionStatsDumper(const char* root_name,
119                                  ProcessMemoryDump* memory_dump,
120                                  MemoryDumpLevelOfDetail level_of_detail);
121 
122   static constexpr char kPartitionsDumpName[] = "partitions";
123 
124   // PartitionStatsDumper implementation.
125   void PartitionDumpTotals(
126       const char* partition_name,
127       const partition_alloc::PartitionMemoryStats*) override;
128   void PartitionsDumpBucketStats(
129       const char* partition_name,
130       const partition_alloc::PartitionBucketMemoryStats*) override;
131 
132   size_t total_mmapped_bytes() const { return total_mmapped_bytes_; }
133   size_t total_resident_bytes() const { return total_resident_bytes_; }
134   size_t total_active_bytes() const { return total_active_bytes_; }
135   size_t total_active_count() const { return total_active_count_; }
136   uint64_t syscall_count() const { return syscall_count_; }
137   size_t cumulative_brp_quarantined_bytes() const {
138     return cumulative_brp_quarantined_bytes_;
139   }
140   size_t cumulative_brp_quarantined_count() const {
141     return cumulative_brp_quarantined_count_;
142   }
143 
144  private:
145   const char* root_name_;
146   raw_ptr<base::trace_event::ProcessMemoryDump> memory_dump_;
147   uint64_t uid_ = 0;
148   size_t total_mmapped_bytes_ = 0;
149   size_t total_resident_bytes_ = 0;
150   size_t total_active_bytes_ = 0;
151   size_t total_active_count_ = 0;
152   uint64_t syscall_count_ = 0;
153   size_t cumulative_brp_quarantined_bytes_ = 0;
154   size_t cumulative_brp_quarantined_count_ = 0;
155   bool detailed_;
156 };
157 
158 #endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC)
159 
160 }  // namespace trace_event
161 }  // namespace base
162 
163 #endif  // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
164