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