Home | History | Annotate | Line # | Download | only in benchmarks
      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))
     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 
     30 struct 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 
     41 struct 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 
     52 struct 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 
     64 template <class AllocWrapper>
     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>
     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>
     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 
    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