summaryrefslogtreecommitdiffstats
path: root/chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-24 11:30:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-30 12:56:19 +0000
commit6036726eb981b6c4b42047513b9d3f4ac865daac (patch)
tree673593e70678e7789766d1f732eb51f613a2703b /chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h
parent466052c4e7c052268fd931888cd58961da94c586 (diff)
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h')
-rw-r--r--chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h b/chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h
new file mode 100644
index 00000000000..b9a34f85631
--- /dev/null
+++ b/chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h
@@ -0,0 +1,123 @@
+// Copyright 2018 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 BASE_SAMPLING_HEAP_PROFILER_POISSON_ALLOCATION_SAMPLER_H_
+#define BASE_SAMPLING_HEAP_PROFILER_POISSON_ALLOCATION_SAMPLER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+
+template <typename T>
+class NoDestructor;
+
+class LockFreeAddressHashSet;
+
+// This singleton class implements Poisson sampling of the incoming allocations
+// stream. It hooks onto base::allocator and base::PartitionAlloc.
+// An extra custom allocator can be hooked via SetHooksInstallCallback method.
+// The only control parameter is sampling interval that controls average value
+// of the sampling intervals. The actual intervals between samples are
+// randomized using Poisson distribution to mitigate patterns in the allocation
+// stream.
+// Once accumulated allocation sizes fill up the current sample interval,
+// a sample is generated and sent to the observers via |SampleAdded| call.
+// When the corresponding memory that triggered the sample is freed observers
+// get notified with |SampleRemoved| call.
+//
+class BASE_EXPORT PoissonAllocationSampler {
+ public:
+ enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC, kMax };
+
+ 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;
+ };
+
+ // The instance of this class makes sampler do not report samples generated
+ // within the object scope for the current thread.
+ // It allows observers to allocate/deallocate memory while holding a lock
+ // without a chance to get into reentrancy problems.
+ class BASE_EXPORT MuteThreadSamplesScope {
+ public:
+ MuteThreadSamplesScope();
+ ~MuteThreadSamplesScope();
+ };
+
+ // Must be called early during the process initialization. It creates and
+ // reserves a TLS slot.
+ static void Init();
+
+ // 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 PoissonAllocationSampler::RecordAlloc and
+ // PoissonAllocationSampler::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*);
+
+ void Start();
+ void Stop();
+ void SetSamplingInterval(size_t sampling_interval);
+ void SuppressRandomnessForTest(bool suppress);
+
+ static void RecordAlloc(void* address,
+ size_t,
+ AllocatorType,
+ const char* context);
+ static void RecordFree(void* address);
+
+ static PoissonAllocationSampler* Get();
+
+ private:
+ PoissonAllocationSampler();
+ ~PoissonAllocationSampler() = delete;
+
+ static void InstallAllocatorHooksOnce();
+ static bool InstallAllocatorHooks();
+ static size_t GetNextSampleInterval(size_t base_interval);
+ static LockFreeAddressHashSet& sampled_addresses_set();
+
+ void DoRecordAlloc(size_t total_allocated,
+ size_t allocation_size,
+ void* address,
+ AllocatorType type,
+ const char* context);
+ void DoRecordFree(void* address);
+
+ void BalanceAddressesHashSet();
+
+ ThreadLocalBoolean entered_;
+ Lock mutex_;
+ std::vector<std::unique_ptr<LockFreeAddressHashSet>> sampled_addresses_stack_;
+ std::vector<SamplesObserver*> observers_;
+
+ static PoissonAllocationSampler* instance_;
+
+ friend class MuteThreadSamplesScope;
+ friend class NoDestructor<PoissonAllocationSampler>;
+
+ DISALLOW_COPY_AND_ASSIGN(PoissonAllocationSampler);
+};
+
+} // namespace base
+
+#endif // BASE_SAMPLING_HEAP_PROFILER_POISSON_ALLOCATION_SAMPLER_H_