1 //===-- Benchmark ---------------------------------------------------------===// 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 "LibcMemoryBenchmarkMain.h" 10 #include "JSON.h" 11 #include "LibcBenchmark.h" 12 #include "LibcMemoryBenchmark.h" 13 #include "llvm/Support/CommandLine.h" 14 #include "llvm/Support/ErrorHandling.h" 15 #include "llvm/Support/FileSystem.h" 16 #include "llvm/Support/JSON.h" 17 #include "llvm/Support/MemoryBuffer.h" 18 #include "llvm/Support/raw_ostream.h" 19 20 #include <string> 21 22 namespace llvm { 23 namespace libc_benchmarks { 24 25 static cl::opt<std::string> 26 Configuration("conf", cl::desc("Specify configuration filename"), 27 cl::value_desc("filename"), cl::init("")); 28 29 static cl::opt<std::string> Output("o", cl::desc("Specify output filename"), 30 cl::value_desc("filename"), cl::init("-")); 31 32 extern std::unique_ptr<BenchmarkRunner> 33 getRunner(const StudyConfiguration &Conf); 34 35 void Main() { 36 #ifndef NDEBUG 37 static_assert( 38 false, 39 "For reproducibility benchmarks should not be compiled in DEBUG mode."); 40 #endif 41 checkRequirements(); 42 ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 43 MemoryBuffer::getFileOrSTDIN(Configuration); 44 if (!MB) 45 report_fatal_error( 46 Twine("Could not open configuration file: ").concat(Configuration)); 47 auto ErrorOrStudy = ParseJsonStudy((*MB)->getBuffer()); 48 if (!ErrorOrStudy) 49 report_fatal_error(ErrorOrStudy.takeError()); 50 51 const auto StudyPrototype = *ErrorOrStudy; 52 53 Study S; 54 S.Host = HostState::get(); 55 S.Options = StudyPrototype.Options; 56 S.Configuration = StudyPrototype.Configuration; 57 58 const auto Runs = S.Configuration.Runs; 59 const auto &SR = S.Configuration.Size; 60 std::unique_ptr<BenchmarkRunner> Runner = getRunner(S.Configuration); 61 const size_t TotalSteps = 62 Runner->getFunctionNames().size() * Runs * ((SR.To - SR.From) / SR.Step); 63 size_t Steps = 0; 64 for (auto FunctionName : Runner->getFunctionNames()) { 65 FunctionMeasurements FM; 66 FM.Name = std::string(FunctionName); 67 for (size_t Run = 0; Run < Runs; ++Run) { 68 for (uint32_t Size = SR.From; Size <= SR.To; Size += SR.Step) { 69 const auto Result = Runner->benchmark(S.Options, FunctionName, Size); 70 Measurement Measurement; 71 Measurement.Runtime = Result.BestGuess; 72 Measurement.Size = Size; 73 FM.Measurements.push_back(Measurement); 74 outs() << format("%3d%% run: %2d / %2d size: %5d ", 75 (Steps * 100 / TotalSteps), Run, Runs, Size) 76 << FunctionName 77 << " \r"; 78 ++Steps; 79 } 80 } 81 S.Functions.push_back(std::move(FM)); 82 } 83 84 std::error_code EC; 85 raw_fd_ostream FOS(Output, EC); 86 if (EC) 87 report_fatal_error(Twine("Could not open file: ") 88 .concat(EC.message()) 89 .concat(", ") 90 .concat(Output)); 91 json::OStream JOS(FOS); 92 SerializeToJson(S, JOS); 93 } 94 95 } // namespace libc_benchmarks 96 } // namespace llvm 97 98 int main(int argc, char **argv) { 99 llvm::cl::ParseCommandLineOptions(argc, argv); 100 llvm::libc_benchmarks::Main(); 101 return EXIT_SUCCESS; 102 } 103