1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This program measures the time taken to decode the given JSON files (the 6 // command line arguments). It is for manual benchmarking. 7 // 8 // Usage: 9 // $ ninja -C out/foobar json_perftest_decodebench 10 // $ out/foobar/json_perftest_decodebench -a -n=10 the/path/to/your/*.json 11 // 12 // The -n=10 switch controls the number of iterations. It defaults to 1. 13 // 14 // The -a switch means to print 1 non-comment line per input file (the average 15 // iteration time). Without this switch (the default), it prints n non-comment 16 // lines per input file (individual iteration times). For a single input file, 17 // building and running this program before and after a particular commit can 18 // work well with the 'ministat' tool: https://github.com/thorduri/ministat 19 20 #include <inttypes.h> 21 #include <iomanip> 22 #include <iostream> 23 24 #include "base/command_line.h" 25 #include "base/files/file_util.h" 26 #include "base/json/json_reader.h" 27 #include "base/logging.h" 28 #include "base/time/time.h" 29 main(int argc,char * argv[])30int main(int argc, char* argv[]) { 31 if (!base::ThreadTicks::IsSupported()) { 32 std::cout << "# base::ThreadTicks is not supported\n"; 33 return EXIT_FAILURE; 34 } 35 base::ThreadTicks::WaitUntilInitialized(); 36 37 base::CommandLine::Init(argc, argv); 38 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 39 bool average = command_line->HasSwitch("a"); 40 int iterations = 1; 41 std::string iterations_str = command_line->GetSwitchValueASCII("n"); 42 if (!iterations_str.empty()) { 43 iterations = atoi(iterations_str.c_str()); 44 if (iterations < 1) { 45 std::cout << "# invalid -n command line switch\n"; 46 return EXIT_FAILURE; 47 } 48 } 49 50 if (average) { 51 std::cout << "# Microseconds (μs), n=" << iterations << ", averaged" 52 << std::endl; 53 } else { 54 std::cout << "# Microseconds (μs), n=" << iterations << std::endl; 55 } 56 for (const auto& filename : command_line->GetArgs()) { 57 std::string src; 58 if (!base::ReadFileToString(base::FilePath(filename), &src)) { 59 std::cout << "# could not read " << filename << std::endl; 60 return EXIT_FAILURE; 61 } 62 63 int64_t total_time = 0; 64 std::string error_message; 65 for (int i = 0; i < iterations; ++i) { 66 auto start = base::ThreadTicks::Now(); 67 auto v = base::JSONReader::ReadAndReturnValueWithError(src); 68 auto end = base::ThreadTicks::Now(); 69 int64_t iteration_time = (end - start).InMicroseconds(); 70 total_time += iteration_time; 71 72 if (i == 0) { 73 if (average) { 74 error_message = 75 !v.has_value() ? std::move(v.error().message) : std::string(); 76 } else { 77 std::cout << "# " << filename; 78 if (!v.has_value() && !v.error().message.empty()) { 79 std::cout << ": " << v.error().message; 80 } 81 std::cout << std::endl; 82 } 83 } 84 85 if (!average) { 86 std::cout << iteration_time << std::endl; 87 } 88 } 89 90 if (average) { 91 int64_t average_time = total_time / iterations; 92 std::cout << std::setw(12) << average_time << "\t# " << filename; 93 if (!error_message.empty()) { 94 std::cout << ": " << error_message; 95 } 96 std::cout << std::endl; 97 } 98 } 99 return EXIT_SUCCESS; 100 } 101