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