llvm/mlir/include/mlir/Support/Timing.h

//===- 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