diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-24 11:30:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-30 12:56:19 +0000 |
commit | 6036726eb981b6c4b42047513b9d3f4ac865daac (patch) | |
tree | 673593e70678e7789766d1f732eb51f613a2703b /chromium/base/sampling_heap_profiler/poisson_allocation_sampler.h | |
parent | 466052c4e7c052268fd931888cd58961da94c586 (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.h | 123 |
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_ |