1 #include "LibcBenchmark.h" 2 #include "LibcMemoryBenchmark.h" 3 #include "MemorySizeDistributions.h" 4 #include "benchmark/benchmark.h" 5 #include "llvm/ADT/ArrayRef.h" 6 #include "llvm/ADT/Twine.h" 7 #include <chrono> 8 #include <cstdint> 9 #include <random> 10 #include <vector> 11 12 using llvm::Align; 13 using llvm::ArrayRef; 14 using llvm::Twine; 15 using llvm::libc_benchmarks::BzeroConfiguration; 16 using llvm::libc_benchmarks::ComparisonSetup; 17 using llvm::libc_benchmarks::CopySetup; 18 using llvm::libc_benchmarks::MemcmpOrBcmpConfiguration; 19 using llvm::libc_benchmarks::MemcpyConfiguration; 20 using llvm::libc_benchmarks::MemmoveConfiguration; 21 using llvm::libc_benchmarks::MemorySizeDistribution; 22 using llvm::libc_benchmarks::MemsetConfiguration; 23 using llvm::libc_benchmarks::MoveSetup; 24 using llvm::libc_benchmarks::OffsetDistribution; 25 using llvm::libc_benchmarks::SetSetup; 26 27 // Alignment to use for when accessing the buffers. 28 static constexpr Align kBenchmarkAlignment = Align::Constant<1>(); 29 30 static std::mt19937_64 &getGenerator() { 31 static std::mt19937_64 Generator( 32 std::chrono::system_clock::now().time_since_epoch().count()); 33 return Generator; 34 } 35 36 template <typename SetupType, typename ConfigurationType> struct Runner { 37 Runner(benchmark::State &S, llvm::ArrayRef<ConfigurationType> Configurations) 38 : State(S), Distribution(SetupType::getDistributions()[State.range(0)]), 39 Probabilities(Distribution.Probabilities), 40 SizeSampler(Probabilities.begin(), Probabilities.end()), 41 OffsetSampler(Setup.BufferSize, Probabilities.size() - 1, 42 kBenchmarkAlignment), 43 Configuration(Configurations[State.range(1)]) { 44 for (auto &P : Setup.Parameters) { 45 P.OffsetBytes = OffsetSampler(getGenerator()); 46 P.SizeBytes = SizeSampler(getGenerator()); 47 Setup.checkValid(P); 48 } 49 } 50 51 ~Runner() { 52 const size_t AvgBytesPerIteration = Setup.getBatchBytes() / Setup.BatchSize; 53 const size_t TotalBytes = State.iterations() * AvgBytesPerIteration; 54 State.SetBytesProcessed(TotalBytes); 55 State.SetItemsProcessed(State.iterations()); 56 State.SetLabel((Twine(Configuration.Name) + "," + Distribution.Name).str()); 57 State.counters["bytes_per_cycle"] = benchmark::Counter( 58 TotalBytes / benchmark::CPUInfo::Get().cycles_per_second, 59 benchmark::Counter::kIsRate); 60 } 61 62 inline void runBatch() { 63 for (const auto &P : Setup.Parameters) 64 benchmark::DoNotOptimize(Setup.Call(P, Configuration.Function)); 65 } 66 67 size_t getBatchSize() const { return Setup.BatchSize; } 68 69 private: 70 SetupType Setup; 71 benchmark::State &State; 72 MemorySizeDistribution Distribution; 73 ArrayRef<double> Probabilities; 74 std::discrete_distribution<unsigned> SizeSampler; 75 OffsetDistribution OffsetSampler; 76 ConfigurationType Configuration; 77 }; 78 79 #define BENCHMARK_MEMORY_FUNCTION(BM_NAME, SETUP, CONFIGURATION_TYPE, \ 80 CONFIGURATION_ARRAY_REF) \ 81 void BM_NAME(benchmark::State &State) { \ 82 Runner<SETUP, CONFIGURATION_TYPE> Setup(State, CONFIGURATION_ARRAY_REF); \ 83 const size_t BatchSize = Setup.getBatchSize(); \ 84 while (State.KeepRunningBatch(BatchSize)) \ 85 Setup.runBatch(); \ 86 } \ 87 BENCHMARK(BM_NAME)->Apply([](benchmark::internal::Benchmark *benchmark) { \ 88 const int64_t DistributionSize = SETUP::getDistributions().size(); \ 89 const int64_t ConfigurationSize = CONFIGURATION_ARRAY_REF.size(); \ 90 for (int64_t DistIndex = 0; DistIndex < DistributionSize; ++DistIndex) \ 91 for (int64_t ConfIndex = 0; ConfIndex < ConfigurationSize; ++ConfIndex) \ 92 benchmark->Args({DistIndex, ConfIndex}); \ 93 }) 94 95 extern llvm::ArrayRef<MemcpyConfiguration> getMemcpyConfigurations(); 96 BENCHMARK_MEMORY_FUNCTION(BM_Memcpy, CopySetup, MemcpyConfiguration, 97 getMemcpyConfigurations()); 98 99 extern llvm::ArrayRef<MemmoveConfiguration> getMemmoveConfigurations(); 100 BENCHMARK_MEMORY_FUNCTION(BM_Memmove, MoveSetup, MemmoveConfiguration, 101 getMemmoveConfigurations()); 102 103 extern llvm::ArrayRef<MemcmpOrBcmpConfiguration> getMemcmpConfigurations(); 104 BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpOrBcmpConfiguration, 105 getMemcmpConfigurations()); 106 107 extern llvm::ArrayRef<MemcmpOrBcmpConfiguration> getBcmpConfigurations(); 108 BENCHMARK_MEMORY_FUNCTION(BM_Bcmp, ComparisonSetup, MemcmpOrBcmpConfiguration, 109 getBcmpConfigurations()); 110 111 extern llvm::ArrayRef<MemsetConfiguration> getMemsetConfigurations(); 112 BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration, 113 getMemsetConfigurations()); 114 115 extern llvm::ArrayRef<BzeroConfiguration> getBzeroConfigurations(); 116 BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration, 117 getBzeroConfigurations()); 118