json_perftest_decodebench.cc 3.3 KB

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