blob: 236e74044a56fe9e87bc1352e835ae06774ceb6a [file] [log] [blame]
Eric Fiselier7445a3f2019-08-02 21:13:38 +00001//===----------------------------------------------------------------------===//
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
15struct PointerList {
16 PointerList* Next = nullptr;
17};
18
19struct MallocWrapper {
20 __attribute__((always_inline))
21 static void* Allocate(size_t N) {
22 return std::malloc(N);
23 }
24 __attribute__((always_inline))
25 static void Deallocate(void* P, size_t) {
26 std::free(P);
27 }
28};
29
30struct NewWrapper {
31 __attribute__((always_inline))
32 static void* Allocate(size_t N) {
33 return ::operator new(N);
34 }
35 __attribute__((always_inline))
36 static void Deallocate(void* P, size_t) {
37 ::operator delete(P);
38 }
39};
40
41struct BuiltinNewWrapper {
42 __attribute__((always_inline))
43 static void* Allocate(size_t N) {
44 return __builtin_operator_new(N);
45 }
46 __attribute__((always_inline))
47 static void Deallocate(void* P, size_t) {
48 __builtin_operator_delete(P);
49 }
50};
51
52struct BuiltinSizedNewWrapper {
53 __attribute__((always_inline))
54 static void* Allocate(size_t N) {
55 return __builtin_operator_new(N);
56 }
57 __attribute__((always_inline))
58 static void Deallocate(void* P, size_t N) {
59 __builtin_operator_delete(P, N);
60 }
61};
62
63
64template <class AllocWrapper>
65static 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
75template <class AllocWrapper>
76static 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
95template <class AllocWrapper>
96static 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
115static 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}
134int Sink = RegisterAllocBenchmarks();
135
136BENCHMARK_MAIN();