Home | History | Annotate | Download | only in sampling_heap_profiler
      1 // Copyright 2018 The Chromium Authors. All rights reserved.
      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_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
      6 #define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
      7 
      8 #include <memory>
      9 #include <stack>
     10 #include <unordered_map>
     11 #include <vector>
     12 
     13 #include "base/base_export.h"
     14 #include "base/macros.h"
     15 #include "base/synchronization/lock.h"
     16 #include "base/threading/thread_local.h"
     17 
     18 namespace base {
     19 
     20 template <typename T>
     21 class NoDestructor;
     22 
     23 class LockFreeAddressHashSet;
     24 
     25 // The class implements sampling profiling of native memory heap.
     26 // It hooks on base::allocator and base::PartitionAlloc.
     27 // When started it selects and records allocation samples based on
     28 // the sampling_interval parameter.
     29 // The recorded samples can then be retrieved using GetSamples method.
     30 class BASE_EXPORT SamplingHeapProfiler {
     31  public:
     32   class BASE_EXPORT Sample {
     33    public:
     34     Sample(const Sample&);
     35     ~Sample();
     36 
     37     size_t size;   // Allocation size.
     38     size_t total;  // Total size attributed to the sample.
     39     std::vector<void*> stack;
     40 
     41    private:
     42     friend class SamplingHeapProfiler;
     43 
     44     Sample(size_t, size_t total, uint32_t ordinal);
     45 
     46     uint32_t ordinal;
     47   };
     48 
     49   class SamplesObserver {
     50    public:
     51     virtual ~SamplesObserver() = default;
     52     virtual void SampleAdded(uint32_t id, size_t size, size_t total) = 0;
     53     virtual void SampleRemoved(uint32_t id) = 0;
     54   };
     55 
     56   // Must be called early during the process initialization. It creates and
     57   // reserves a TLS slot.
     58   static void InitTLSSlot();
     59 
     60   // This is an entry point for plugging in an external allocator.
     61   // Profiler will invoke the provided callback upon initialization.
     62   // The callback should install hooks onto the corresponding memory allocator
     63   // and make them invoke SamplingHeapProfiler::RecordAlloc and
     64   // SamplingHeapProfiler::RecordFree upon corresponding allocation events.
     65   //
     66   // If the method is called after profiler is initialized, the callback
     67   // is invoked right away.
     68   static void SetHooksInstallCallback(void (*hooks_install_callback)());
     69 
     70   void AddSamplesObserver(SamplesObserver*);
     71   void RemoveSamplesObserver(SamplesObserver*);
     72 
     73   uint32_t Start();
     74   void Stop();
     75   void SetSamplingInterval(size_t sampling_interval);
     76   void SuppressRandomnessForTest(bool suppress);
     77 
     78   std::vector<Sample> GetSamples(uint32_t profile_id);
     79 
     80   static void RecordAlloc(void* address, size_t, uint32_t skip_frames = 0);
     81   static void RecordFree(void* address);
     82 
     83   static SamplingHeapProfiler* GetInstance();
     84 
     85  private:
     86   SamplingHeapProfiler();
     87   ~SamplingHeapProfiler() = delete;
     88 
     89   static void InstallAllocatorHooksOnce();
     90   static bool InstallAllocatorHooks();
     91   static size_t GetNextSampleInterval(size_t base_interval);
     92 
     93   void DoRecordAlloc(size_t total_allocated,
     94                      size_t allocation_size,
     95                      void* address,
     96                      uint32_t skip_frames);
     97   void DoRecordFree(void* address);
     98   void RecordStackTrace(Sample*, uint32_t skip_frames);
     99   static LockFreeAddressHashSet& sampled_addresses_set();
    100 
    101   void BalanceAddressesHashSet();
    102 
    103   base::ThreadLocalBoolean entered_;
    104   base::Lock mutex_;
    105   std::stack<std::unique_ptr<LockFreeAddressHashSet>> sampled_addresses_stack_;
    106   std::unordered_map<void*, Sample> samples_;
    107   std::vector<SamplesObserver*> observers_;
    108   uint32_t last_sample_ordinal_ = 1;
    109 
    110   static SamplingHeapProfiler* instance_;
    111 
    112   friend class base::NoDestructor<SamplingHeapProfiler>;
    113 
    114   DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler);
    115 };
    116 
    117 }  // namespace base
    118 
    119 #endif  // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
    120