Commit 6f282594 authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

[heap profiler] Make first allocation on each thread properly accounted.

Previously we used to skip first allocation on each thread.
That accounts for certain amount of memory, especially when there
are lots of threads.

BUG=1007491

Change-Id: Ibe990c6094355183833fdfc598a0e8c0196a8aaf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825727
Commit-Queue: Alexei Filippov <alph@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700028}
parent 1be83044
......@@ -412,11 +412,11 @@ void PoissonAllocationSampler::RecordAlloc(void* address,
return;
if (UNLIKELY(!g_running.load(std::memory_order_relaxed))) {
// Sampling is in fact disabled. Put a large negative value into
// the accumulator. It needs to be large enough to have this code
// not trigger frequently, and small enough to eventually start collecting
// samples when the sampling is enabled.
g_accumulated_bytes_tls = -static_cast<intptr_t>(kWarmupInterval);
// Sampling is in fact disabled. Reset the state of the sampler.
// We do this check off the fast-path, because it's quite a rare state when
// allocation hooks are installed but the sampler is not running.
g_sampling_interval_initialized_tls = false;
g_accumulated_bytes_tls = 0;
return;
}
......@@ -433,6 +433,21 @@ void PoissonAllocationSampler::DoRecordAlloc(intptr_t accumulated_bytes,
return;
size_t mean_interval = g_sampling_interval.load(std::memory_order_relaxed);
if (UNLIKELY(!g_sampling_interval_initialized_tls)) {
g_sampling_interval_initialized_tls = true;
// This is the very first allocation on the thread. It always makes it
// passing the condition at |RecordAlloc|, because g_accumulated_bytes_tls
// is initialized with zero due to TLS semantics.
// Generate proper sampling interval instance and make sure the allocation
// has indeed crossed the threshold before counting it as a sample.
accumulated_bytes -= GetNextSampleInterval(mean_interval);
if (accumulated_bytes < 0) {
g_accumulated_bytes_tls = accumulated_bytes;
return;
}
}
size_t samples = accumulated_bytes / mean_interval;
accumulated_bytes %= mean_interval;
......@@ -443,16 +458,6 @@ void PoissonAllocationSampler::DoRecordAlloc(intptr_t accumulated_bytes,
g_accumulated_bytes_tls = accumulated_bytes;
if (UNLIKELY(!g_sampling_interval_initialized_tls)) {
g_sampling_interval_initialized_tls = true;
// This is the very first allocation on the thread. It always produces an
// extra sample because g_accumulated_bytes_tls is initialized with zero
// due to TLS semantics.
// Make sure we don't count this extra sample.
if (!--samples)
return;
}
if (UNLIKELY(ScopedMuteThreadSamples::IsMuted()))
return;
......
......@@ -35,10 +35,6 @@ class BASE_EXPORT PoissonAllocationSampler {
public:
enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC };
// When the sampler is just enabled it needs to see up to that amount
// of allocation sizes before it starts recording samples.
static constexpr size_t kWarmupInterval = 1 << 20; // 1MB.
class SamplesObserver {
public:
virtual ~SamplesObserver() = default;
......
......@@ -757,10 +757,6 @@ void TestDriver::MakeTestAllocations() {
base::PlatformThread::SetName(kThreadName);
// Warm up the sampler. Once enabled it may need to see up to 1MB of
// allocations to start sampling.
leaks_.push_back(new char[base::PoissonAllocationSampler::kWarmupInterval]);
// In sampling mode, only sampling allocations are relevant.
if (!IsRecordingAllAllocations()) {
leaks_.reserve(kSamplingAllocCount);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment