Nigel Tao | f909626 | 2020-04-29 01:46:12 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors. All rights reserved. |
| 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" |
Hans Wennborg | afeb390 | 2020-06-17 14:42:29 | [diff] [blame] | 27 | #include "base/logging.h" |
Nigel Tao | f909626 | 2020-04-29 01:46:12 | [diff] [blame] | 28 | #include "base/time/time.h" |
| 29 | |
| 30 | int 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 = std::move(v.error_message); |
| 75 | } else { |
| 76 | std::cout << "# " << filename; |
| 77 | if (!v.error_message.empty()) { |
| 78 | std::cout << ": " << v.error_message; |
| 79 | } |
| 80 | std::cout << std::endl; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | if (!average) { |
| 85 | std::cout << iteration_time << std::endl; |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | if (average) { |
| 90 | int64_t average_time = total_time / iterations; |
| 91 | std::cout << std::setw(12) << average_time << "\t# " << filename; |
| 92 | if (!error_message.empty()) { |
| 93 | std::cout << ": " << error_message; |
| 94 | } |
| 95 | std::cout << std::endl; |
| 96 | } |
| 97 | } |
| 98 | return EXIT_SUCCESS; |
| 99 | } |