forked from scylladb/seastar
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Imports the sampler.h file from the Android Open Source Project from: https://cs.android.com/android/platform/superproject/+/013901367630d3ec71c9f2bb3f3077bd11585301:external/perfetto/src/profiling/memory/sampler.h In this commit the file is imported as is. The adaption to seastar and our needs is done in a following commit. This is so that it stays clear what was originally imported and what our changes are.
- Loading branch information
1 parent
b6984c7
commit 045eec6
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright (C) 2018 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#ifndef SRC_PROFILING_MEMORY_SAMPLER_H_ | ||
#define SRC_PROFILING_MEMORY_SAMPLER_H_ | ||
|
||
#include <stdint.h> | ||
|
||
#include <atomic> | ||
#include <random> | ||
|
||
#include "perfetto/ext/base/utils.h" | ||
|
||
namespace perfetto { | ||
namespace profiling { | ||
|
||
constexpr uint64_t kSamplerSeed = 1; | ||
|
||
std::default_random_engine& GetGlobalRandomEngineLocked(); | ||
|
||
// Poisson sampler for memory allocations. We apply sampling individually to | ||
// each byte. The whole allocation gets accounted as often as the number of | ||
// sampled bytes it contains. | ||
// | ||
// The algorithm is inspired by the Chromium sampling algorithm at | ||
// https://cs.chromium.org/search/?q=f:cc+symbol:AllocatorShimLogAlloc+package:%5Echromium$&type=cs | ||
// Googlers: see go/chrome-shp for more details. | ||
// | ||
// NB: not thread-safe, requires external synchronization. | ||
class Sampler { | ||
public: | ||
void SetSamplingInterval(uint64_t sampling_interval) { | ||
sampling_interval_ = sampling_interval; | ||
sampling_rate_ = 1.0 / static_cast<double>(sampling_interval_); | ||
interval_to_next_sample_ = NextSampleInterval(); | ||
} | ||
|
||
// Returns number of bytes that should be be attributed to the sample. | ||
// If returned size is 0, the allocation should not be sampled. | ||
// | ||
// Due to how the poission sampling works, some samples should be accounted | ||
// multiple times. | ||
size_t SampleSize(size_t alloc_sz) { | ||
if (PERFETTO_UNLIKELY(alloc_sz >= sampling_interval_)) | ||
return alloc_sz; | ||
return static_cast<size_t>(sampling_interval_ * NumberOfSamples(alloc_sz)); | ||
} | ||
|
||
uint64_t sampling_interval() const { return sampling_interval_; } | ||
|
||
private: | ||
int64_t NextSampleInterval() { | ||
std::exponential_distribution<double> dist(sampling_rate_); | ||
int64_t next = static_cast<int64_t>(dist(GetGlobalRandomEngineLocked())); | ||
// We approximate the geometric distribution using an exponential | ||
// distribution. | ||
// We need to add 1 because that gives us the number of failures before | ||
// the next success, while our interval includes the next success. | ||
return next + 1; | ||
} | ||
|
||
// Returns number of times a sample should be accounted. Due to how the | ||
// poission sampling works, some samples should be accounted multiple times. | ||
size_t NumberOfSamples(size_t alloc_sz) { | ||
interval_to_next_sample_ -= alloc_sz; | ||
size_t num_samples = 0; | ||
while (PERFETTO_UNLIKELY(interval_to_next_sample_ <= 0)) { | ||
interval_to_next_sample_ += NextSampleInterval(); | ||
++num_samples; | ||
} | ||
return num_samples; | ||
} | ||
|
||
uint64_t sampling_interval_; | ||
double sampling_rate_; | ||
int64_t interval_to_next_sample_; | ||
}; | ||
|
||
} // namespace profiling | ||
} // namespace perfetto | ||
|
||
#endif // SRC_PROFILING_MEMORY_SAMPLER_H_ |