mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
allocator_benchmark.cpp
Go to the documentation of this file.
1#include <chrono>
2#include <cstdint>
3#include <iostream>
6#include <type_traits>
7#include <vector>
8
9
10using namespace std::chrono;
11
12#ifndef NDEBUG
13static constexpr std::size_t NUM_ALLOCATIONS_START = 1UL<<10;
14static constexpr std::size_t NUM_ALLOCATIONS_STOP = 1UL<<13;
15#else
16static constexpr std::size_t NUM_ALLOCATIONS_START = 1UL<<10;
17static constexpr std::size_t NUM_ALLOCATIONS_STOP = 1UL<<16;
18#endif
19
20
21constexpr unsigned long long operator ""_Ki(unsigned long long n) { return n * 1024; }
22constexpr unsigned long long operator ""_Mi(unsigned long long n) { return n * 1024 * 1024; }
23constexpr unsigned long long operator ""_Gi(unsigned long long n) { return n * 1024 * 1024 * 1024; }
24
25template<typename Allocator>
26void run_benchmark_allocations_fixed_allocate(const std::string &name, const Allocator &proto,
27 const float fraction_deallocate, const std::size_t size)
28{
29 for (std::size_t num_allocations = NUM_ALLOCATIONS_START;
30 num_allocations <= NUM_ALLOCATIONS_STOP;
31 num_allocations *= 2)
32 {
33 Allocator A(proto); // copy
34 std::vector<void*> allocations(num_allocations);
35 float p_dealloc = 0.f;
36 std::size_t idx_dealloc = 0;
37
38 auto begin = steady_clock::now();
39 for (auto &allocation : allocations) {
40 allocation = A.allocate(size);
41 uint8_t *ptr = reinterpret_cast<uint8_t*>(allocation);
42 *ptr = size; // enforce page fault
43
44 p_dealloc += fraction_deallocate;
45 if (p_dealloc >= 1.f) {
46 p_dealloc -= 1.f;
47 A.deallocate(allocations[idx_dealloc++], size);
48 }
49 }
50 auto end = steady_clock::now();
51
52 std::cout << "fixed_allocate," << name << ',' << size << ',' << fraction_deallocate << ','
53 << num_allocations << ',' << duration_cast<microseconds>(end - begin).count() / 1e3 << std::endl;
54 for (; idx_dealloc != num_allocations; ++idx_dealloc)
55 A.deallocate(allocations[idx_dealloc], size);
56 }
57}
58
59template<typename Allocator>
60void run_benchmark_allocations_fixed_allocate_then_deallocate(const std::string &name, const Allocator &proto,
61 const std::size_t size)
62{
63 for (std::size_t num_allocations = NUM_ALLOCATIONS_START;
64 num_allocations <= NUM_ALLOCATIONS_STOP;
65 num_allocations *= 2)
66 {
67 Allocator A(proto); // copy
68 std::vector<void*> allocations(num_allocations);
69
70 auto begin = steady_clock::now();
71 for (auto &allocation : allocations) {
72 allocation = A.allocate(size);
73 uint8_t *ptr = reinterpret_cast<uint8_t*>(allocation);
74 *ptr = size; // enforce page fault
75 }
76 for (auto allocation : allocations) {
77 A.deallocate(allocation, size);
78 }
79 auto end = steady_clock::now();
80
81 std::cout << "fixed_allocate_then_deallocate," << name << ',' << size << ',' << 1.f << ','
82 << num_allocations << ',' << duration_cast<microseconds>(end - begin).count() / 1e3 << std::endl;
83 }
84}
85
86template<typename Allocator>
87void run_benchmark_allocations_fixed_allocate_then_deallocate_reversed(const std::string &name, const Allocator &proto,
88 const std::size_t size)
89{
90 for (std::size_t num_allocations = NUM_ALLOCATIONS_START;
91 num_allocations <= NUM_ALLOCATIONS_STOP >> 2U;
92 num_allocations *= 2)
93 {
94 Allocator A(proto); // copy
95 std::vector<void*> allocations(num_allocations);
96
97 auto begin = steady_clock::now();
98 for (auto &allocation : allocations) {
99 allocation = A.allocate(size);
100 uint8_t *ptr = reinterpret_cast<uint8_t*>(allocation);
101 *ptr = size; // enforce page fault
102 }
103 for (auto it = allocations.crbegin(); it != allocations.crend(); ++it) {
104 A.deallocate(*it, size);
105 }
106 auto end = steady_clock::now();
107
108 std::cout << "fixed_allocate_then_deallocate_reversed," << name << ',' << size << ',' << 1.f << ','
109 << num_allocations << ',' << duration_cast<microseconds>(end - begin).count() / 1e3 << std::endl;
110 }
111}
112
113template<typename Allocator>
114void run_benchmark_suite_for_allocator(const std::string &name, const Allocator &proto)
115{
116 for (float p : { 0.f, .5f, 1.f}) {
118 run_benchmark_allocations_fixed_allocate(name, proto, p, 4_Ki);
119 run_benchmark_allocations_fixed_allocate(name, proto, p, 64_Ki);
120#ifdef NDEBUG
121 run_benchmark_allocations_fixed_allocate(name, proto, p, 8_Mi);
122 run_benchmark_allocations_fixed_allocate(name, proto, p, 128_Mi);
123#endif
124 }
125
129#ifdef NDEBUG
132#endif
133
137#ifdef NDEBUG
140#endif
141}
142
143
144int main(void)
145{
146 std::cout << "type,allocator,size,p_dealloc,count,time" << std::endl;
149 run_benchmark_suite_for_allocator("list<Linear-64K>", m::list_allocator(64_Ki));
154}
void run_benchmark_suite_for_allocator(const std::string &name, const Allocator &proto)
void run_benchmark_allocations_fixed_allocate(const std::string &name, const Allocator &proto, const float fraction_deallocate, const std::size_t size)
void run_benchmark_allocations_fixed_allocate_then_deallocate_reversed(const std::string &name, const Allocator &proto, const std::size_t size)
int main(void)
static constexpr std::size_t NUM_ALLOCATIONS_START
void run_benchmark_allocations_fixed_allocate_then_deallocate(const std::string &name, const Allocator &proto, const std::size_t size)
static constexpr std::size_t NUM_ALLOCATIONS_STOP
Implements a list allocator.
This allocator serves allocations using malloc/free.