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