allocation.bench.cpp 3.5 KB

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