Commit 4f8aac4c authored by erikchen's avatar erikchen Committed by Commit Bot

Fix OOP HP implementation of poisson process sampling.

To correctly implement poisson process sampling, we occasionally have to take
multiple samples from a single allocation. Since the memlog stream format does
not support a "count" or "weight" parameter, use "sz" as a proxy.

Bug: 810748
Change-Id: Ie87be75b0915afd5d032943f8a42cb5a190ce6e5
Reviewed-on: https://chromium-review.googlesource.com/922982Reviewed-by: default avatarPrimiano Tucci <primiano@chromium.org>
Commit-Queue: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537361}
parent 7ea6cf78
...@@ -690,30 +690,34 @@ void AllocatorShimLogAlloc(AllocatorType type, ...@@ -690,30 +690,34 @@ void AllocatorShimLogAlloc(AllocatorType type,
if (!send_buffers) if (!send_buffers)
return; return;
// Sample allocations smaller than g_sampling_rate. Always record larger // When sampling, we divide allocations into two buckets. For allocations
// allocations. [There's no point in sampling larger allocations since we // larger than g_sampling_rate we just skip the sampling logic entirely, since
// want to record them with probability 1. Just do that.] // we want to record them with probability 1. Allocations smaller than
// g_sampling_rate we use a poisson process to sample. That gives us a
// computationally cheap mechanism to sample allocations with probability P =
// (size) / g_sampling_rate.
if (g_sample_allocations && LIKELY(sz < g_sampling_rate)) { if (g_sample_allocations && LIKELY(sz < g_sampling_rate)) {
ShimState* shim_state = GetShimState(); ShimState* shim_state = GetShimState();
// Update the sampling interval, if necessary. This also handles the case
// where the sampling interval has not yet been initialized.
//
// interval_to_next_sample is actually an underflowing counter that
// triggers a sample. Incrementing by GetNextSampleInterval() provides a
// poisson process sampling of allocations with probability = (sz /
// g_sampling_rate).
if (shim_state->interval_to_next_sample <= 0) {
shim_state->interval_to_next_sample +=
GetNextSampleInterval(g_sampling_rate);
}
shim_state->interval_to_next_sample -= sz; shim_state->interval_to_next_sample -= sz;
// Do not sample the allocation. // When |interval_to_next_sample| underflows, we record a sample.
if (shim_state->interval_to_next_sample > 0) { if (LIKELY(shim_state->interval_to_next_sample > 0)) {
return; return;
} }
// Very occasionally, when sampling, we'll want to take more than 1 sample
// from the same object. Ideally, we'd have a "count" or "weight" associated
// with the allocation in question. Since the memlog stream format does not
// support that, just use |sz| as a proxy.
int sz_multiplier = 0;
while (shim_state->interval_to_next_sample <= 0) {
shim_state->interval_to_next_sample +=
GetNextSampleInterval(g_sampling_rate);
++sz_multiplier;
}
sz *= sz_multiplier;
} }
if (address) { if (address) {
......
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