xref: /netbsd-src/external/apache2/llvm/dist/libcxx/benchmarks/allocation.bench.cpp (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg //===----------------------------------------------------------------------===//
2*4d6fc14bSjoerg //
3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d6fc14bSjoerg //
7*4d6fc14bSjoerg //===----------------------------------------------------------------------===//
8*4d6fc14bSjoerg 
9*4d6fc14bSjoerg #include "benchmark/benchmark.h"
10*4d6fc14bSjoerg 
11*4d6fc14bSjoerg #include <new>
12*4d6fc14bSjoerg #include <vector>
13*4d6fc14bSjoerg #include <cassert>
14*4d6fc14bSjoerg 
15*4d6fc14bSjoerg struct PointerList {
16*4d6fc14bSjoerg   PointerList* Next = nullptr;
17*4d6fc14bSjoerg };
18*4d6fc14bSjoerg 
19*4d6fc14bSjoerg struct MallocWrapper {
20*4d6fc14bSjoerg   __attribute__((always_inline))
AllocateMallocWrapper21*4d6fc14bSjoerg   static void* Allocate(size_t N) {
22*4d6fc14bSjoerg     return std::malloc(N);
23*4d6fc14bSjoerg   }
24*4d6fc14bSjoerg   __attribute__((always_inline))
DeallocateMallocWrapper25*4d6fc14bSjoerg   static void Deallocate(void* P, size_t) {
26*4d6fc14bSjoerg     std::free(P);
27*4d6fc14bSjoerg   }
28*4d6fc14bSjoerg };
29*4d6fc14bSjoerg 
30*4d6fc14bSjoerg struct NewWrapper {
31*4d6fc14bSjoerg   __attribute__((always_inline))
AllocateNewWrapper32*4d6fc14bSjoerg   static void* Allocate(size_t N) {
33*4d6fc14bSjoerg     return ::operator new(N);
34*4d6fc14bSjoerg   }
35*4d6fc14bSjoerg   __attribute__((always_inline))
DeallocateNewWrapper36*4d6fc14bSjoerg   static void Deallocate(void* P, size_t) {
37*4d6fc14bSjoerg     ::operator delete(P);
38*4d6fc14bSjoerg   }
39*4d6fc14bSjoerg };
40*4d6fc14bSjoerg 
41*4d6fc14bSjoerg struct BuiltinNewWrapper {
42*4d6fc14bSjoerg   __attribute__((always_inline))
AllocateBuiltinNewWrapper43*4d6fc14bSjoerg   static void* Allocate(size_t N) {
44*4d6fc14bSjoerg     return __builtin_operator_new(N);
45*4d6fc14bSjoerg   }
46*4d6fc14bSjoerg   __attribute__((always_inline))
DeallocateBuiltinNewWrapper47*4d6fc14bSjoerg   static void Deallocate(void* P, size_t) {
48*4d6fc14bSjoerg     __builtin_operator_delete(P);
49*4d6fc14bSjoerg   }
50*4d6fc14bSjoerg };
51*4d6fc14bSjoerg 
52*4d6fc14bSjoerg struct BuiltinSizedNewWrapper {
53*4d6fc14bSjoerg   __attribute__((always_inline))
AllocateBuiltinSizedNewWrapper54*4d6fc14bSjoerg   static void* Allocate(size_t N) {
55*4d6fc14bSjoerg     return __builtin_operator_new(N);
56*4d6fc14bSjoerg   }
57*4d6fc14bSjoerg   __attribute__((always_inline))
DeallocateBuiltinSizedNewWrapper58*4d6fc14bSjoerg   static void Deallocate(void* P, size_t N) {
59*4d6fc14bSjoerg     __builtin_operator_delete(P, N);
60*4d6fc14bSjoerg   }
61*4d6fc14bSjoerg };
62*4d6fc14bSjoerg 
63*4d6fc14bSjoerg 
64*4d6fc14bSjoerg template <class AllocWrapper>
BM_AllocateAndDeallocate(benchmark::State & st)65*4d6fc14bSjoerg static void BM_AllocateAndDeallocate(benchmark::State& st) {
66*4d6fc14bSjoerg   const size_t alloc_size = st.range(0);
67*4d6fc14bSjoerg   while (st.KeepRunning()) {
68*4d6fc14bSjoerg     void* p = AllocWrapper::Allocate(alloc_size);
69*4d6fc14bSjoerg     benchmark::DoNotOptimize(p);
70*4d6fc14bSjoerg     AllocWrapper::Deallocate(p, alloc_size);
71*4d6fc14bSjoerg   }
72*4d6fc14bSjoerg }
73*4d6fc14bSjoerg 
74*4d6fc14bSjoerg 
75*4d6fc14bSjoerg template <class AllocWrapper>
BM_AllocateOnly(benchmark::State & st)76*4d6fc14bSjoerg static void BM_AllocateOnly(benchmark::State& st) {
77*4d6fc14bSjoerg   const size_t alloc_size = st.range(0);
78*4d6fc14bSjoerg   PointerList *Start = nullptr;
79*4d6fc14bSjoerg 
80*4d6fc14bSjoerg   while (st.KeepRunning()) {
81*4d6fc14bSjoerg     PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);
82*4d6fc14bSjoerg     benchmark::DoNotOptimize(p);
83*4d6fc14bSjoerg     p->Next = Start;
84*4d6fc14bSjoerg     Start = p;
85*4d6fc14bSjoerg   }
86*4d6fc14bSjoerg 
87*4d6fc14bSjoerg   PointerList *Next = Start;
88*4d6fc14bSjoerg   while (Next) {
89*4d6fc14bSjoerg     PointerList *Tmp = Next;
90*4d6fc14bSjoerg     Next = Tmp->Next;
91*4d6fc14bSjoerg     AllocWrapper::Deallocate(Tmp, alloc_size);
92*4d6fc14bSjoerg   }
93*4d6fc14bSjoerg }
94*4d6fc14bSjoerg 
95*4d6fc14bSjoerg template <class AllocWrapper>
BM_DeallocateOnly(benchmark::State & st)96*4d6fc14bSjoerg static void BM_DeallocateOnly(benchmark::State& st) {
97*4d6fc14bSjoerg   const size_t alloc_size = st.range(0);
98*4d6fc14bSjoerg   const auto NumAllocs = st.max_iterations;
99*4d6fc14bSjoerg 
100*4d6fc14bSjoerg   using PtrT = void*;
101*4d6fc14bSjoerg   std::vector<void*> Pointers(NumAllocs);
102*4d6fc14bSjoerg   for (auto& p : Pointers) {
103*4d6fc14bSjoerg     p = AllocWrapper::Allocate(alloc_size);
104*4d6fc14bSjoerg   }
105*4d6fc14bSjoerg 
106*4d6fc14bSjoerg   void** Data = Pointers.data();
107*4d6fc14bSjoerg   void** const End = Pointers.data() + Pointers.size();
108*4d6fc14bSjoerg   while (st.KeepRunning()) {
109*4d6fc14bSjoerg     AllocWrapper::Deallocate(*Data, alloc_size);
110*4d6fc14bSjoerg     Data += 1;
111*4d6fc14bSjoerg   }
112*4d6fc14bSjoerg   assert(Data == End);
113*4d6fc14bSjoerg }
114*4d6fc14bSjoerg 
RegisterAllocBenchmarks()115*4d6fc14bSjoerg static int RegisterAllocBenchmarks() {
116*4d6fc14bSjoerg   using FnType = void(*)(benchmark::State&);
117*4d6fc14bSjoerg   struct {
118*4d6fc14bSjoerg     const char* name;
119*4d6fc14bSjoerg     FnType func;
120*4d6fc14bSjoerg   } TestCases[] = {
121*4d6fc14bSjoerg       {"BM_Malloc", &BM_AllocateAndDeallocate<MallocWrapper>},
122*4d6fc14bSjoerg       {"BM_New", &BM_AllocateAndDeallocate<NewWrapper>},
123*4d6fc14bSjoerg       {"BM_BuiltinNewDelete", BM_AllocateAndDeallocate<BuiltinNewWrapper>},
124*4d6fc14bSjoerg       {"BM_BuiltinSizedNewDelete", BM_AllocateAndDeallocate<BuiltinSizedNewWrapper>},
125*4d6fc14bSjoerg       {"BM_BuiltinNewAllocateOnly", BM_AllocateOnly<BuiltinSizedNewWrapper>},
126*4d6fc14bSjoerg       {"BM_BuiltinNewSizedDeallocateOnly", BM_DeallocateOnly<BuiltinSizedNewWrapper>},
127*4d6fc14bSjoerg 
128*4d6fc14bSjoerg   };
129*4d6fc14bSjoerg   for (auto TC : TestCases) {
130*4d6fc14bSjoerg     benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);
131*4d6fc14bSjoerg   }
132*4d6fc14bSjoerg   return 0;
133*4d6fc14bSjoerg }
134*4d6fc14bSjoerg int Sink = RegisterAllocBenchmarks();
135*4d6fc14bSjoerg 
136*4d6fc14bSjoerg BENCHMARK_MAIN();
137