xref: /aosp_15_r20/external/cronet/third_party/libc++/src/benchmarks/allocation.bench.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 <cassert>
12 #include <new>
13 #include <vector>
14 
15 struct PointerList {
16   PointerList* Next = nullptr;
17 };
18 
19 struct MallocWrapper {
AllocateMallocWrapper20   __attribute__((always_inline)) static void* Allocate(size_t N) { return std::malloc(N); }
DeallocateMallocWrapper21   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { std::free(P); }
22 };
23 
24 struct NewWrapper {
AllocateNewWrapper25   __attribute__((always_inline)) static void* Allocate(size_t N) { return ::operator new(N); }
DeallocateNewWrapper26   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { ::operator delete(P); }
27 };
28 
29 struct BuiltinNewWrapper {
AllocateBuiltinNewWrapper30   __attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }
DeallocateBuiltinNewWrapper31   __attribute__((always_inline)) static void Deallocate(void* P, size_t) { __builtin_operator_delete(P); }
32 };
33 
34 struct BuiltinSizedNewWrapper {
AllocateBuiltinSizedNewWrapper35   __attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }
DeallocateBuiltinSizedNewWrapper36   __attribute__((always_inline)) static void Deallocate(void* P, size_t N) { __builtin_operator_delete(P, N); }
37 };
38 
39 template <class AllocWrapper>
BM_AllocateAndDeallocate(benchmark::State & st)40 static void BM_AllocateAndDeallocate(benchmark::State& st) {
41   const size_t alloc_size = st.range(0);
42   while (st.KeepRunning()) {
43     void* p = AllocWrapper::Allocate(alloc_size);
44     benchmark::DoNotOptimize(p);
45     AllocWrapper::Deallocate(p, alloc_size);
46   }
47 }
48 
49 template <class AllocWrapper>
BM_AllocateOnly(benchmark::State & st)50 static void BM_AllocateOnly(benchmark::State& st) {
51   const size_t alloc_size = st.range(0);
52   PointerList* Start      = nullptr;
53 
54   while (st.KeepRunning()) {
55     PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);
56     benchmark::DoNotOptimize(p);
57     p->Next = Start;
58     Start   = p;
59   }
60 
61   PointerList* Next = Start;
62   while (Next) {
63     PointerList* Tmp = Next;
64     Next             = Tmp->Next;
65     AllocWrapper::Deallocate(Tmp, alloc_size);
66   }
67 }
68 
69 template <class AllocWrapper>
BM_DeallocateOnly(benchmark::State & st)70 static void BM_DeallocateOnly(benchmark::State& st) {
71   const size_t alloc_size = st.range(0);
72   const auto NumAllocs    = st.max_iterations;
73 
74   std::vector<void*> Pointers(NumAllocs);
75   for (auto& p : Pointers) {
76     p = AllocWrapper::Allocate(alloc_size);
77   }
78 
79   void** Data                       = Pointers.data();
80   [[maybe_unused]] void** const End = Pointers.data() + Pointers.size();
81   while (st.KeepRunning()) {
82     AllocWrapper::Deallocate(*Data, alloc_size);
83     Data += 1;
84   }
85   assert(Data == End);
86 }
87 
RegisterAllocBenchmarks()88 static int RegisterAllocBenchmarks() {
89   using FnType = void (*)(benchmark::State&);
90   struct {
91     const char* name;
92     FnType func;
93   } TestCases[] = {
94       {"BM_Malloc", &BM_AllocateAndDeallocate<MallocWrapper>},
95       {"BM_New", &BM_AllocateAndDeallocate<NewWrapper>},
96       {"BM_BuiltinNewDelete", BM_AllocateAndDeallocate<BuiltinNewWrapper>},
97       {"BM_BuiltinSizedNewDelete", BM_AllocateAndDeallocate<BuiltinSizedNewWrapper>},
98       {"BM_BuiltinNewAllocateOnly", BM_AllocateOnly<BuiltinSizedNewWrapper>},
99       {"BM_BuiltinNewSizedDeallocateOnly", BM_DeallocateOnly<BuiltinSizedNewWrapper>},
100 
101   };
102   for (auto TC : TestCases) {
103     benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);
104   }
105   return 0;
106 }
107 int Sink = RegisterAllocBenchmarks();
108 
109 BENCHMARK_MAIN();
110