Skip to content

Commit 5804d49

Browse files
committed
disable fragmentation output for peak benchmark
1 parent 6c576c1 commit 5804d49

File tree

1 file changed

+86
-82
lines changed

1 file changed

+86
-82
lines changed

benchmark/benchmark.hpp

Lines changed: 86 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
303303
typename std::vector<next_alloc_data>::const_iterator;
304304
std::vector<std::unique_ptr<next_alloc_data_iterator>> next_iter;
305305
int64_t iterations;
306+
bool log_fragmentation;
307+
multiple_malloc_free_benchmark(bool log_fragmentation = true)
308+
: log_fragmentation(log_fragmentation) {}
306309

307310
public:
308311
void SetUp(::benchmark::State &state) override {
@@ -350,7 +353,7 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
350353
void TearDown(::benchmark::State &state) override {
351354
base::allocator.postBench(state);
352355
auto tid = state.thread_index();
353-
if (tid == 0) {
356+
if (tid == 0 && log_fragmentation) {
354357
size_t current_memory_allocated = 0;
355358
for (const auto &allocationsPerThread : allocations) {
356359
for (const auto &allocation : allocationsPerThread) {
@@ -518,87 +521,88 @@ template <
518521
class peak_alloc_benchmark
519522
: public multiple_malloc_free_benchmark<Size, Alloc> {
520523
using base = multiple_malloc_free_benchmark<Size, Alloc>;
521-
virtual void prepareWorkload(benchmark::State &state) override {
522-
// Retrieve the thread index and corresponding operation buffer.
523-
auto tid = state.thread_index();
524-
auto &n = this->next[tid];
525-
526-
// Set up the random generators for index selection and decision making.
527-
std::default_random_engine generator;
528-
std::uniform_int_distribution<size_t> dist_offset(0,
529-
this->max_allocs - 1);
530-
std::uniform_real_distribution<double> dist_opt_type(0, 1);
531-
generator.seed(0);
532-
auto sizeGenerator = this->alloc_sizes[tid];
533-
534-
n.clear();
535-
std::vector<size_t> free;
536-
std::vector<size_t> allocated;
537-
free.reserve(this->max_allocs);
538-
// Initially, all indices are available.
539-
for (size_t i = 0; i < this->max_allocs; i++) {
540-
free.push_back(i);
541-
}
542-
543-
// Total number of allocation/free operations to simulate.
544-
int64_t operations_number =
545-
state.max_iterations * this->allocsPerIterations;
546-
for (int64_t j = 0; j < operations_number; j++) {
547-
int64_t target_allocation;
548-
549-
// Determine the target number of allocations based on the progress of the iterations.
550-
// In the first half of the iterations, the target allocation increases linearly.
551-
// In the second half, it decreases linearly.
552-
if (j < operations_number / 2) {
553-
target_allocation = 2 * static_cast<int64_t>(this->max_allocs) *
554-
j / operations_number;
555-
} else {
556-
target_allocation = -2 *
557-
static_cast<int64_t>(this->max_allocs) *
558-
j / operations_number +
559-
2 * static_cast<int64_t>(this->max_allocs);
560-
}
561-
562-
// x represents the gap between the target and current allocations.
563-
auto x = static_cast<double>(target_allocation -
564-
static_cast<double>(allocated.size()));
565-
566-
// Use a normal CDF with high sigma so that when x is positive,
567-
// we are slightly more likely to allocate,
568-
// and when x is negative, slightly more likely to free memory,
569-
// keeping the overall change gradual.
570-
571-
const double sigma = 1000;
572-
auto cdf = normalCDF(x, sigma);
573-
574-
// Decide whether to allocate or free:
575-
// - If no allocations exist, allocation is forced.
576-
// - If there is maximum number of allocation, free is forced
577-
// - Otherwise, Based on the computed probability, choose whether to allocate or free
578-
if (allocated.empty() ||
579-
(!free.empty() && cdf > dist_opt_type(generator))) {
580-
// Allocation
581-
std::swap(free[dist_offset(generator) % free.size()],
582-
free.back());
583-
auto offset = free.back();
584-
free.pop_back();
585-
n.push_back({true, offset, sizeGenerator.nextSize()});
586-
allocated.push_back(offset);
587-
} else {
588-
// Free
589-
std::swap(allocated[dist_offset(generator) % allocated.size()],
590-
allocated.back());
591-
auto offset = allocated.back();
592-
allocated.pop_back();
593-
n.push_back({false, offset, 0});
594-
free.push_back(offset);
595-
}
596-
}
597-
598-
this->next_iter[tid] =
599-
std::make_unique<std::vector<next_alloc_data>::const_iterator>(
600-
n.cbegin());
601-
}
524+
public:
525+
peak_alloc_benchmark() : base(false) {}
526+
virtual void prepareWorkload(benchmark::State &state) override {
527+
// Retrieve the thread index and corresponding operation buffer.
528+
auto tid = state.thread_index();
529+
auto &n = this->next[tid];
530+
531+
// Set up the random generators for index selection and decision making.
532+
std::default_random_engine generator;
533+
std::uniform_int_distribution<size_t> dist_offset(0,
534+
this->max_allocs - 1);
535+
std::uniform_real_distribution<double> dist_opt_type(0, 1);
536+
generator.seed(0);
537+
auto sizeGenerator = this->alloc_sizes[tid];
538+
539+
n.clear();
540+
std::vector<size_t> free;
541+
std::vector<size_t> allocated;
542+
free.reserve(this->max_allocs);
543+
// Initially, all indices are available.
544+
for (size_t i = 0; i < this->max_allocs; i++) {
545+
free.push_back(i);
546+
}
547+
548+
// Total number of allocation/free operations to simulate.
549+
int64_t operations_number =
550+
state.max_iterations * this->allocsPerIterations;
551+
for (int64_t j = 0; j < operations_number; j++) {
552+
int64_t target_allocation;
553+
554+
// Determine the target number of allocations based on the progress of the iterations.
555+
// In the first half of the iterations, the target allocation increases linearly.
556+
// In the second half, it decreases linearly.
557+
if (j < operations_number / 2) {
558+
target_allocation = 2 * static_cast<int64_t>(this->max_allocs) *
559+
j / operations_number;
560+
} else {
561+
target_allocation = -2 * static_cast<int64_t>(this->max_allocs) *
562+
j / operations_number +
563+
2 * static_cast<int64_t>(this->max_allocs);
564+
}
565+
566+
// x represents the gap between the target and current allocations.
567+
auto x = static_cast<double>(target_allocation -
568+
static_cast<double>(allocated.size()));
569+
570+
// Use a normal CDF with high sigma so that when x is positive,
571+
// we are slightly more likely to allocate,
572+
// and when x is negative, slightly more likely to free memory,
573+
// keeping the overall change gradual.
574+
575+
const double sigma = 1000;
576+
auto cdf = normalCDF(x, sigma);
577+
578+
// Decide whether to allocate or free:
579+
// - If no allocations exist, allocation is forced.
580+
// - If there is maximum number of allocation, free is forced
581+
// - Otherwise, Based on the computed probability, choose whether to allocate or free
582+
if (allocated.empty() ||
583+
(!free.empty() && cdf > dist_opt_type(generator))) {
584+
// Allocation
585+
std::swap(free[dist_offset(generator) % free.size()],
586+
free.back());
587+
auto offset = free.back();
588+
free.pop_back();
589+
n.push_back({true, offset, sizeGenerator.nextSize()});
590+
allocated.push_back(offset);
591+
} else {
592+
// Free
593+
std::swap(allocated[dist_offset(generator) % allocated.size()],
594+
allocated.back());
595+
auto offset = allocated.back();
596+
allocated.pop_back();
597+
n.push_back({false, offset, 0});
598+
free.push_back(offset);
599+
}
600+
}
601+
602+
this->next_iter[tid] =
603+
std::make_unique<std::vector<next_alloc_data>::const_iterator>(
604+
n.cbegin());
605+
}
602606

603607
virtual void prealloc(benchmark::State &state) {
604608
auto tid = state.thread_index();

0 commit comments

Comments
 (0)