Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/Support/TimeProfiler.h - Hierarchical Time Profiler -*- C++ -*-===//
  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. // This provides lightweight and dependency-free machinery to trace execution
  10. // time around arbitrary code. Two API flavors are available.
  11. //
  12. // The primary API uses a RAII object to trigger tracing:
  13. //
  14. // \code
  15. //   {
  16. //     TimeTraceScope scope("my_event_name");
  17. //     ...my code...
  18. //   }
  19. // \endcode
  20. //
  21. // If the code to be profiled does not have a natural lexical scope then
  22. // it is also possible to start and end events with respect to an implicit
  23. // per-thread stack of profiling entries:
  24. //
  25. // \code
  26. //   timeTraceProfilerBegin("my_event_name");
  27. //   ...my code...
  28. //   timeTraceProfilerEnd();  // must be called on all control flow paths
  29. // \endcode
  30. //
  31. // Time profiling entries can be given an arbitrary name and, optionally,
  32. // an arbitrary 'detail' string. The resulting trace will include 'Total'
  33. // entries summing the time spent for each name. Thus, it's best to choose
  34. // names to be fairly generic, and rely on the detail field to capture
  35. // everything else of interest.
  36. //
  37. // To avoid lifetime issues name and detail strings are copied into the event
  38. // entries at their time of creation. Care should be taken to make string
  39. // construction cheap to prevent 'Heisenperf' effects. In particular, the
  40. // 'detail' argument may be a string-returning closure:
  41. //
  42. // \code
  43. //   int n;
  44. //   {
  45. //     TimeTraceScope scope("my_event_name",
  46. //                          [n]() { return (Twine("x=") + Twine(n)).str(); });
  47. //     ...my code...
  48. //   }
  49. // \endcode
  50. // The closure will not be called if tracing is disabled. Otherwise, the
  51. // resulting string will be directly moved into the entry.
  52. //
  53. // The main process should begin with a timeTraceProfilerInitialize, and
  54. // finish with timeTraceProfileWrite and timeTraceProfilerCleanup calls.
  55. // Each new thread should begin with a timeTraceProfilerInitialize, and
  56. // finish with a timeTraceProfilerFinishThread call.
  57. //
  58. // Timestamps come from std::chrono::stable_clock. Note that threads need
  59. // not see the same time from that clock, and the resolution may not be
  60. // the best available.
  61. //
  62. // Currently, there are a number of compatible viewers:
  63. //  - chrome://tracing is the original chromium trace viewer.
  64. //  - http://ui.perfetto.dev is the replacement for the above, under active
  65. //    development by Google as part of the 'Perfetto' project.
  66. //  - https://www.speedscope.app/ has also been reported as an option.
  67. //
  68. // Future work:
  69. //  - Support akin to LLVM_DEBUG for runtime enable/disable of named tracing
  70. //    families for non-debug builds which wish to support optional tracing.
  71. //  - Evaluate the detail closures at profile write time to avoid
  72. //    stringification costs interfering with tracing.
  73. //
  74. //===----------------------------------------------------------------------===//
  75.  
  76. #ifndef LLVM_SUPPORT_TIMEPROFILER_H
  77. #define LLVM_SUPPORT_TIMEPROFILER_H
  78.  
  79. #include "llvm/ADT/STLFunctionalExtras.h"
  80. #include "llvm/Support/Error.h"
  81.  
  82. namespace llvm {
  83.  
  84. class raw_pwrite_stream;
  85.  
  86. struct TimeTraceProfiler;
  87. TimeTraceProfiler *getTimeTraceProfilerInstance();
  88.  
  89. /// Initialize the time trace profiler.
  90. /// This sets up the global \p TimeTraceProfilerInstance
  91. /// variable to be the profiler instance.
  92. void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
  93.                                  StringRef ProcName);
  94.  
  95. /// Cleanup the time trace profiler, if it was initialized.
  96. void timeTraceProfilerCleanup();
  97.  
  98. /// Finish a time trace profiler running on a worker thread.
  99. void timeTraceProfilerFinishThread();
  100.  
  101. /// Is the time trace profiler enabled, i.e. initialized?
  102. inline bool timeTraceProfilerEnabled() {
  103.   return getTimeTraceProfilerInstance() != nullptr;
  104. }
  105.  
  106. /// Write profiling data to output stream.
  107. /// Data produced is JSON, in Chrome "Trace Event" format, see
  108. /// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
  109. void timeTraceProfilerWrite(raw_pwrite_stream &OS);
  110.  
  111. /// Write profiling data to a file.
  112. /// The function will write to \p PreferredFileName if provided, if not
  113. /// then will write to \p FallbackFileName appending .time-trace.
  114. /// Returns a StringError indicating a failure if the function is
  115. /// unable to open the file for writing.
  116. Error timeTraceProfilerWrite(StringRef PreferredFileName,
  117.                              StringRef FallbackFileName);
  118.  
  119. /// Manually begin a time section, with the given \p Name and \p Detail.
  120. /// Profiler copies the string data, so the pointers can be given into
  121. /// temporaries. Time sections can be hierarchical; every Begin must have a
  122. /// matching End pair but they can nest.
  123. void timeTraceProfilerBegin(StringRef Name, StringRef Detail);
  124. void timeTraceProfilerBegin(StringRef Name,
  125.                             llvm::function_ref<std::string()> Detail);
  126.  
  127. /// Manually end the last time section.
  128. void timeTraceProfilerEnd();
  129.  
  130. /// The TimeTraceScope is a helper class to call the begin and end functions
  131. /// of the time trace profiler.  When the object is constructed, it begins
  132. /// the section; and when it is destroyed, it stops it. If the time profiler
  133. /// is not initialized, the overhead is a single branch.
  134. struct TimeTraceScope {
  135.  
  136.   TimeTraceScope() = delete;
  137.   TimeTraceScope(const TimeTraceScope &) = delete;
  138.   TimeTraceScope &operator=(const TimeTraceScope &) = delete;
  139.   TimeTraceScope(TimeTraceScope &&) = delete;
  140.   TimeTraceScope &operator=(TimeTraceScope &&) = delete;
  141.  
  142.   TimeTraceScope(StringRef Name) {
  143.     if (getTimeTraceProfilerInstance() != nullptr)
  144.       timeTraceProfilerBegin(Name, StringRef(""));
  145.   }
  146.   TimeTraceScope(StringRef Name, StringRef Detail) {
  147.     if (getTimeTraceProfilerInstance() != nullptr)
  148.       timeTraceProfilerBegin(Name, Detail);
  149.   }
  150.   TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
  151.     if (getTimeTraceProfilerInstance() != nullptr)
  152.       timeTraceProfilerBegin(Name, Detail);
  153.   }
  154.   ~TimeTraceScope() {
  155.     if (getTimeTraceProfilerInstance() != nullptr)
  156.       timeTraceProfilerEnd();
  157.   }
  158. };
  159.  
  160. } // end namespace llvm
  161.  
  162. #endif
  163.