llvm-project
109 строк · 3.5 Кб
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
15struct PointerList {16PointerList* Next = nullptr;17};18
19struct MallocWrapper {20__attribute__((always_inline)) static void* Allocate(size_t N) { return std::malloc(N); }21__attribute__((always_inline)) static void Deallocate(void* P, size_t) { std::free(P); }22};23
24struct NewWrapper {25__attribute__((always_inline)) static void* Allocate(size_t N) { return ::operator new(N); }26__attribute__((always_inline)) static void Deallocate(void* P, size_t) { ::operator delete(P); }27};28
29struct BuiltinNewWrapper {30__attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }31__attribute__((always_inline)) static void Deallocate(void* P, size_t) { __builtin_operator_delete(P); }32};33
34struct BuiltinSizedNewWrapper {35__attribute__((always_inline)) static void* Allocate(size_t N) { return __builtin_operator_new(N); }36__attribute__((always_inline)) static void Deallocate(void* P, size_t N) { __builtin_operator_delete(P, N); }37};38
39template <class AllocWrapper>40static void BM_AllocateAndDeallocate(benchmark::State& st) {41const size_t alloc_size = st.range(0);42while (st.KeepRunning()) {43void* p = AllocWrapper::Allocate(alloc_size);44benchmark::DoNotOptimize(p);45AllocWrapper::Deallocate(p, alloc_size);46}47}
48
49template <class AllocWrapper>50static void BM_AllocateOnly(benchmark::State& st) {51const size_t alloc_size = st.range(0);52PointerList* Start = nullptr;53
54while (st.KeepRunning()) {55PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);56benchmark::DoNotOptimize(p);57p->Next = Start;58Start = p;59}60
61PointerList* Next = Start;62while (Next) {63PointerList* Tmp = Next;64Next = Tmp->Next;65AllocWrapper::Deallocate(Tmp, alloc_size);66}67}
68
69template <class AllocWrapper>70static void BM_DeallocateOnly(benchmark::State& st) {71const size_t alloc_size = st.range(0);72const auto NumAllocs = st.max_iterations;73
74std::vector<void*> Pointers(NumAllocs);75for (auto& p : Pointers) {76p = AllocWrapper::Allocate(alloc_size);77}78
79void** Data = Pointers.data();80[[maybe_unused]] void** const End = Pointers.data() + Pointers.size();81while (st.KeepRunning()) {82AllocWrapper::Deallocate(*Data, alloc_size);83Data += 1;84}85assert(Data == End);86}
87
88static int RegisterAllocBenchmarks() {89using FnType = void (*)(benchmark::State&);90struct {91const char* name;92FnType 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};102for (auto TC : TestCases) {103benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);104}105return 0;106}
107int Sink = RegisterAllocBenchmarks();108
109BENCHMARK_MAIN();110