[sampling heap profiler] Extract Poisson sampler into a separate class.
Make Poisson sampler a separate class that is responsible for listening
for allocation and doing the sampling with given sampling interval.
SamplingHeapProfiler is now an observer of PoissonAllocationObserver.
Once a sample added it record the native stack and stores the sample
in the map. The list of recorded samples can then be retrieved by clients.
[email protected]
BUG=803276
Change-Id: I1e568b9839d9cc0099704ba1b9f047c14a46a0ee
Reviewed-on: https://chromium-review.googlesource.com/1189713
Reviewed-by: Alexei Filippov <[email protected]>
Reviewed-by: Kentaro Hara <[email protected]>
Reviewed-by: Erik Chen <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Commit-Queue: Alexei Filippov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#586369}
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.h b/base/sampling_heap_profiler/sampling_heap_profiler.h
index 1ef7f3f..194fdd3 100644
--- a/base/sampling_heap_profiler/sampling_heap_profiler.h
+++ b/base/sampling_heap_profiler/sampling_heap_profiler.h
@@ -5,13 +5,12 @@
#ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
#define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
-#include <memory>
-#include <stack>
#include <unordered_map>
#include <vector>
#include "base/base_export.h"
#include "base/macros.h"
+#include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
@@ -20,17 +19,13 @@
template <typename T>
class NoDestructor;
-class LockFreeAddressHashSet;
-
// The class implements sampling profiling of native memory heap.
-// It hooks on base::allocator and base::PartitionAlloc.
-// When started it selects and records allocation samples based on
-// the sampling_interval parameter.
+// It uses PoissonAllocationSampler to aggregate the heap allocations and
+// record samples.
// The recorded samples can then be retrieved using GetSamples method.
-class BASE_EXPORT SamplingHeapProfiler {
+class BASE_EXPORT SamplingHeapProfiler
+ : private PoissonAllocationSampler::SamplesObserver {
public:
- enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC, kMax };
-
class BASE_EXPORT Sample {
public:
Sample(const Sample&);
@@ -48,80 +43,33 @@
uint32_t ordinal;
};
- class SamplesObserver {
- public:
- virtual ~SamplesObserver() = default;
- virtual void SampleAdded(void* address,
- size_t size,
- size_t total,
- AllocatorType type,
- const char* context) = 0;
- virtual void SampleRemoved(void* address) = 0;
- };
-
- // Must be called early during the process initialization. It creates and
- // reserves a TLS slot.
- static void InitTLSSlot();
-
- // This is an entry point for plugging in an external allocator.
- // Profiler will invoke the provided callback upon initialization.
- // The callback should install hooks onto the corresponding memory allocator
- // and make them invoke SamplingHeapProfiler::RecordAlloc and
- // SamplingHeapProfiler::RecordFree upon corresponding allocation events.
- //
- // If the method is called after profiler is initialized, the callback
- // is invoked right away.
- static void SetHooksInstallCallback(void (*hooks_install_callback)());
-
- void AddSamplesObserver(SamplesObserver*);
- void RemoveSamplesObserver(SamplesObserver*);
-
uint32_t Start();
void Stop();
void SetSamplingInterval(size_t sampling_interval);
- void SuppressRandomnessForTest(bool suppress);
std::vector<Sample> GetSamples(uint32_t profile_id);
- static void RecordAlloc(void* address,
- size_t,
- AllocatorType,
- const char* context,
- uint32_t skip_frames = 0);
- static void RecordFree(void* address);
-
- static SamplingHeapProfiler* GetInstance();
+ static void Init();
+ static SamplingHeapProfiler* Get();
private:
SamplingHeapProfiler();
- ~SamplingHeapProfiler() = delete;
+ ~SamplingHeapProfiler() override;
- static void InstallAllocatorHooksOnce();
- static bool InstallAllocatorHooks();
- static size_t GetNextSampleInterval(size_t base_interval);
+ // PoissonAllocationSampler::SamplesObserver
+ void SampleAdded(void* address,
+ size_t size,
+ size_t total,
+ PoissonAllocationSampler::AllocatorType type,
+ const char* context) override;
+ void SampleRemoved(void* address) override;
- void DoRecordAlloc(size_t total_allocated,
- size_t allocation_size,
- void* address,
- AllocatorType type,
- const char* context,
- uint32_t skip_frames);
- void DoRecordFree(void* address);
- void RecordStackTrace(Sample*, uint32_t skip_frames);
- static LockFreeAddressHashSet& sampled_addresses_set();
-
- void BalanceAddressesHashSet();
-
- base::ThreadLocalBoolean entered_;
- base::Lock mutex_;
- std::stack<std::unique_ptr<LockFreeAddressHashSet>> sampled_addresses_stack_;
+ ThreadLocalBoolean entered_;
+ Lock mutex_;
std::unordered_map<void*, Sample> samples_;
- std::vector<SamplesObserver*> observers_;
uint32_t last_sample_ordinal_ = 1;
- static SamplingHeapProfiler* instance_;
-
- friend class base::NoDestructor<SamplingHeapProfiler>;
+ friend class NoDestructor<SamplingHeapProfiler>;
DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler);
};