//===- Timing.h - Execution time measurement facilities ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Facilities to measure and provide statistics on execution time. // //===----------------------------------------------------------------------===// #ifndef MLIR_SUPPORT_TIMING_H #define MLIR_SUPPORT_TIMING_H #include "mlir/Support/LLVM.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMapEntry.h" #include "llvm/Support/raw_ostream.h" #include <optional> namespace mlir { class Timer; class TimingManager; class TimingScope; class DefaultTimingManager; namespace detail { class TimingManagerImpl; class DefaultTimingManagerImpl; } // namespace detail //===----------------------------------------------------------------------===// // TimingIdentifier //===----------------------------------------------------------------------===// /// This class represesents a uniqued string owned by a `TimingManager`. Most /// importantly, instances of this class provide a stable opaque pointer that /// is guaranteed to be reproduced by later interning of the same string. The /// `TimingManager` uses this mechanism to provide timers with an opaque id /// even when the user of the API merely provided a string as identification /// (instead of a pass for example). /// /// This is a POD type with pointer size, so it should be passed around by /// value. The underlying data is owned by the `TimingManager`. class TimingIdentifier { … }; //===----------------------------------------------------------------------===// // TimingManager //===----------------------------------------------------------------------===// /// This class represents facilities to measure execution time. /// /// Libraries and infrastructure code operate on opque `Timer` handles returned /// by various functions of this manager. Timers are started and stopped to /// demarcate regions in the code where execution time is of interest, and they /// can be nested to provide more detailed timing resolution. Calls to the timer /// start, stop, and nesting functions must be balanced. To facilitate this, /// users are encouraged to leverage the `TimingScope` RAII-style wrapper around /// `Timer`s. /// /// Users can provide their own implementation of `TimingManager`, or use the /// default `DefaultTimingManager` implementation in MLIR. Implementations /// override the various protected virtual functions to create, nest, start, and /// stop timers. A common pattern is for subclasses to provide a custom timer /// class and simply pass pointers to instances of this class around as the /// opaque timer handle. The manager itself can then forward callbacks to the /// this class. Alternatively, external timing libraries may return their own /// opaque handles for timing scopes. /// /// For example: /// ``` /// void doWork(TimingManager &tm) { /// auto root = tm.getRootScope(); /// /// { /// auto scope = root.nest("First"); /// doSomeWork(); /// // <-- "First" timer stops here /// } /// /// auto scope = root.nest("Second"); /// doEvenMoreWork(); /// scope.stop(); // <-- "Second" timer stops here /// /// // <-- Root timer stops here /// } /// ``` class TimingManager { … }; //===----------------------------------------------------------------------===// // Timer //===----------------------------------------------------------------------===// /// A handle for a timer in a `TimingManager`. /// /// This class encapsulates a pointer to a `TimingManager` and an opaque handle /// to a timer running within that manager. Libraries and infrastructure code /// operate on `Timer` rather than any concrete classes handed out by custom /// manager implementations. class Timer { … }; //===----------------------------------------------------------------------===// // TimingScope //===----------------------------------------------------------------------===// /// An RAII-style wrapper around a timer that ensures the timer is properly /// started and stopped. class TimingScope { … }; //===----------------------------------------------------------------------===// // OutputStrategy //===----------------------------------------------------------------------===// /// Simple record class to record timing information. struct TimeRecord { … }; /// Facilities for printing timing reports to various output formats. /// /// This is an abstract class that serves as the foundation for printing. /// Users can implement additional output formats by extending this abstract /// class. class OutputStrategy { … }; //===----------------------------------------------------------------------===// // DefaultTimingManager //===----------------------------------------------------------------------===// /// Facilities for time measurement and report printing to an output stream. /// /// This is MLIR's default implementation of a `TimingManager`. Prints an /// execution time report upon destruction, or manually through `print()`. By /// default the results are printed in `DisplayMode::Tree` mode to stderr. /// Use `setEnabled(true)` to enable collection of timing samples; it is /// disabled by default. /// /// You should only instantiate a `DefaultTimingManager` if you are writing a /// tool and want to pass a timing manager to the remaining infrastructure. If /// you are writing library or infrastructure code, you should rather accept /// the `TimingManager` base class to allow for users of your code to substitute /// their own timing implementations. Also, if you only intend to collect time /// samples, consider accepting a `Timer` or `TimingScope` instead. class DefaultTimingManager : public TimingManager { … }; /// Register a set of useful command-line options that can be used to configure /// a `DefaultTimingManager`. The values of these options can be applied via the /// `applyDefaultTimingManagerCLOptions` method. void registerDefaultTimingManagerCLOptions(); /// Apply any values that were registered with /// 'registerDefaultTimingManagerOptions' to a `DefaultTimingManager`. void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm); } // namespace mlir #endif // MLIR_SUPPORT_TIMING_H