• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // REQUIRES: -fsized-deallocation
10 // ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation
11 
12 #include "benchmark/benchmark.h"
13 
14 #include <cassert>
15 #include <cstdlib>
16 #include <new>
17 #include <vector>
18 
19 #include "test_macros.h"
20 
21 struct PointerList {
22   PointerList* Next = nullptr;
23 };
24 
25 struct MallocWrapper {
AllocateMallocWrapper26   __attribute__((always_inline)) static void* Allocate(size_t N) { return std::malloc(N); }
DeallocateMallocWrapper27   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { std::free(P); }
28 };
29 
30 struct NewWrapper {
AllocateNewWrapper31   __attribute__((always_inline)) static void* Allocate(size_t N) { return ::operator new(N); }
DeallocateNewWrapper32   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { ::operator delete(P); }
33 };
34 
35 #ifdef TEST_COMPILER_CLANG
36 struct BuiltinNewWrapper {
AllocateBuiltinNewWrapper37   __attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }
DeallocateBuiltinNewWrapper38   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { __builtin_operator_delete(P); }
39 };
40 
41 struct BuiltinSizedNewWrapper {
AllocateBuiltinSizedNewWrapper42   __attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }
DeallocateBuiltinSizedNewWrapper43   __attribute__((always_inline)) static void Deallocate(void* P, size_t N) { __builtin_operator_delete(P, N); }
44 };
45 #endif
46 
47 template <class AllocWrapper>
BM_AllocateAndDeallocate(benchmark::State & st)48 static void BM_AllocateAndDeallocate(benchmark::State& st) {
49   const size_t alloc_size = st.range(0);
50   while (st.KeepRunning()) {
51     void* p = AllocWrapper::Allocate(alloc_size);
52     benchmark::DoNotOptimize(p);
53     AllocWrapper::Deallocate(p, alloc_size);
54   }
55 }
56 
57 template <class AllocWrapper>
BM_AllocateOnly(benchmark::State & st)58 static void BM_AllocateOnly(benchmark::State& st) {
59   const size_t alloc_size = st.range(0);
60   PointerList* Start      = nullptr;
61 
62   while (st.KeepRunning()) {
63     PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);
64     benchmark::DoNotOptimize(p);
65     p->Next = Start;
66     Start   = p;
67   }
68 
69   PointerList* Next = Start;
70   while (Next) {
71     PointerList* Tmp = Next;
72     Next             = Tmp->Next;
73     AllocWrapper::Deallocate(Tmp, alloc_size);
74   }
75 }
76 
77 template <class AllocWrapper>
BM_DeallocateOnly(benchmark::State & st)78 static void BM_DeallocateOnly(benchmark::State& st) {
79   const size_t alloc_size = st.range(0);
80   const auto NumAllocs    = st.max_iterations;
81 
82   std::vector<void*> Pointers(NumAllocs);
83   for (auto& p : Pointers) {
84     p = AllocWrapper::Allocate(alloc_size);
85   }
86 
87   void** Data                       = Pointers.data();
88   [[maybe_unused]] void** const End = Pointers.data() + Pointers.size();
89   while (st.KeepRunning()) {
90     AllocWrapper::Deallocate(*Data, alloc_size);
91     Data += 1;
92   }
93   assert(Data == End);
94 }
95 
RegisterAllocBenchmarks()96 static int RegisterAllocBenchmarks() {
97   using FnType = void (*)(benchmark::State&);
98   struct {
99     const char* name;
100     FnType func;
101   } TestCases[] = {
102       {"BM_Malloc", &BM_AllocateAndDeallocate<MallocWrapper>},
103       {"BM_New", &BM_AllocateAndDeallocate<NewWrapper>},
104 #ifdef TEST_COMPILER_CLANG
105       {"BM_BuiltinNewDelete", BM_AllocateAndDeallocate<BuiltinNewWrapper>},
106       {"BM_BuiltinSizedNewDelete", BM_AllocateAndDeallocate<BuiltinSizedNewWrapper>},
107       {"BM_BuiltinNewAllocateOnly", BM_AllocateOnly<BuiltinSizedNewWrapper>},
108       {"BM_BuiltinNewSizedDeallocateOnly", BM_DeallocateOnly<BuiltinSizedNewWrapper>},
109 #endif
110   };
111   for (auto TC : TestCases) {
112     benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);
113   }
114   return 0;
115 }
116 int Sink = RegisterAllocBenchmarks();
117 
118 BENCHMARK_MAIN();
119