MicroProfiler.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #include <atomic>
  9. #include <thread>
  10. // #define WITH_MICRO_PROFILER 1
  11. #ifdef WITH_MICRO_PROFILER
  12. #define MICRO_PROFILER_SECTION(name) MicroProfilerSection __b(name)
  13. #define MICRO_PROFILER_SECTION_NAMED(var_name, name) \
  14. MicroProfilerSection var_name(name)
  15. #else
  16. #define MICRO_PROFILER_SECTION(name)
  17. #define MICRO_PROFILER_SECTION_NAMED(var_name, name)
  18. #endif
  19. namespace facebook {
  20. namespace react {
  21. enum MicroProfilerName {
  22. __INTERNAL_BENCHMARK_INNER,
  23. __INTERNAL_BENCHMARK_OUTER,
  24. __LENGTH__,
  25. };
  26. /**
  27. * MicroProfiler is a performance profiler for measuring the cumulative impact
  28. * of a large number of small-ish calls. This is normally a problem for standard
  29. * profilers like Systrace because the overhead of the profiler itself skews the
  30. * timings you are able to collect. This is especially a problem when doing
  31. * nested calls to profiled functions, as the parent calls will contain the
  32. * overhead of their profiling plus the overhead of all their childrens'
  33. * profiling.
  34. *
  35. * MicroProfiler attempts to be low overhead by 1) aggregating timings in memory
  36. * and 2) trying to remove estimated profiling overhead from the returned
  37. * timings.
  38. *
  39. * To remove estimated overhead, at the beginning of each trace we calculate the
  40. * average cost of profiling a no-op code section, as well as invoking the
  41. * average cost of invoking the system clock. The former is subtracted out for
  42. * each child profiler section that is invoked within a parent profiler section.
  43. * The latter is subtracted from each section, child or not.
  44. *
  45. * After MicroProfiler::stopProfiling() is called, a table of tracing data is
  46. * emitted to glog (which shows up in logcat on Android).
  47. */
  48. struct MicroProfiler {
  49. static const char *profilingNameToString(MicroProfilerName name) {
  50. switch (name) {
  51. case __INTERNAL_BENCHMARK_INNER:
  52. return "__INTERNAL_BENCHMARK_INNER";
  53. case __INTERNAL_BENCHMARK_OUTER:
  54. return "__INTERNAL_BENCHMARK_OUTER";
  55. case __LENGTH__:
  56. throw std::runtime_error("__LENGTH__ has no name");
  57. default:
  58. throw std::runtime_error(
  59. "Trying to convert unknown MicroProfilerName to string");
  60. }
  61. }
  62. static void startProfiling();
  63. static void stopProfiling();
  64. static bool isProfiling();
  65. static void runInternalBenchmark();
  66. };
  67. class MicroProfilerSection {
  68. public:
  69. MicroProfilerSection(MicroProfilerName name);
  70. ~MicroProfilerSection();
  71. private:
  72. bool isProfiling_;
  73. MicroProfilerName name_;
  74. uint_fast64_t startTime_;
  75. uint_fast32_t startNumProfileSections_;
  76. };
  77. } // namespace react
  78. } // namespace facebook