Home | History | Annotate | Download | only in Support
      1 //===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_SUPPORT_TIMER_H
     11 #define LLVM_SUPPORT_TIMER_H
     12 
     13 #include "llvm/ADT/StringRef.h"
     14 #include "llvm/Support/Compiler.h"
     15 #include "llvm/Support/DataTypes.h"
     16 #include <cassert>
     17 #include <string>
     18 #include <utility>
     19 #include <vector>
     20 
     21 namespace llvm {
     22 
     23 class Timer;
     24 class TimerGroup;
     25 class raw_ostream;
     26 
     27 class TimeRecord {
     28   double WallTime;       // Wall clock time elapsed in seconds
     29   double UserTime;       // User time elapsed
     30   double SystemTime;     // System time elapsed
     31   ssize_t MemUsed;       // Memory allocated (in bytes)
     32 public:
     33   TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
     34 
     35   /// getCurrentTime - Get the current time and memory usage.  If Start is true
     36   /// we get the memory usage before the time, otherwise we get time before
     37   /// memory usage.  This matters if the time to get the memory usage is
     38   /// significant and shouldn't be counted as part of a duration.
     39   static TimeRecord getCurrentTime(bool Start = true);
     40 
     41   double getProcessTime() const { return UserTime+SystemTime; }
     42   double getUserTime() const { return UserTime; }
     43   double getSystemTime() const { return SystemTime; }
     44   double getWallTime() const { return WallTime; }
     45   ssize_t getMemUsed() const { return MemUsed; }
     46 
     47 
     48   // operator< - Allow sorting.
     49   bool operator<(const TimeRecord &T) const {
     50     // Sort by Wall Time elapsed, as it is the only thing really accurate
     51     return WallTime < T.WallTime;
     52   }
     53 
     54   void operator+=(const TimeRecord &RHS) {
     55     WallTime   += RHS.WallTime;
     56     UserTime   += RHS.UserTime;
     57     SystemTime += RHS.SystemTime;
     58     MemUsed    += RHS.MemUsed;
     59   }
     60   void operator-=(const TimeRecord &RHS) {
     61     WallTime   -= RHS.WallTime;
     62     UserTime   -= RHS.UserTime;
     63     SystemTime -= RHS.SystemTime;
     64     MemUsed    -= RHS.MemUsed;
     65   }
     66 
     67   /// print - Print the current timer to standard error, and reset the "Started"
     68   /// flag.
     69   void print(const TimeRecord &Total, raw_ostream &OS) const;
     70 };
     71 
     72 /// Timer - This class is used to track the amount of time spent between
     73 /// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
     74 /// support it can also keep track of the RSS of the program at various points.
     75 /// By default, the Timer will print the amount of time it has captured to
     76 /// standard error when the last timer is destroyed, otherwise it is printed
     77 /// when its TimerGroup is destroyed.  Timers do not print their information
     78 /// if they are never started.
     79 ///
     80 class Timer {
     81   TimeRecord Time;
     82   std::string Name;      // The name of this time variable.
     83   bool Started;          // Has this time variable ever been started?
     84   TimerGroup *TG;        // The TimerGroup this Timer is in.
     85 
     86   Timer **Prev, *Next;   // Doubly linked list of timers in the group.
     87 public:
     88   explicit Timer(StringRef N) : TG(nullptr) { init(N); }
     89   Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); }
     90   Timer(const Timer &RHS) : TG(nullptr) {
     91     assert(!RHS.TG && "Can only copy uninitialized timers");
     92   }
     93   const Timer &operator=(const Timer &T) {
     94     assert(!TG && !T.TG && "Can only assign uninit timers");
     95     return *this;
     96   }
     97   ~Timer();
     98 
     99   // Create an uninitialized timer, client must use 'init'.
    100   explicit Timer() : TG(nullptr) {}
    101   void init(StringRef N);
    102   void init(StringRef N, TimerGroup &tg);
    103 
    104   const std::string &getName() const { return Name; }
    105   bool isInitialized() const { return TG != nullptr; }
    106 
    107   /// startTimer - Start the timer running.  Time between calls to
    108   /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
    109   /// must be correctly paired.
    110   ///
    111   void startTimer();
    112 
    113   /// stopTimer - Stop the timer.
    114   ///
    115   void stopTimer();
    116 
    117 private:
    118   friend class TimerGroup;
    119 };
    120 
    121 
    122 /// The TimeRegion class is used as a helper class to call the startTimer() and
    123 /// stopTimer() methods of the Timer class.  When the object is constructed, it
    124 /// starts the timer specified as its argument.  When it is destroyed, it stops
    125 /// the relevant timer.  This makes it easy to time a region of code.
    126 ///
    127 class TimeRegion {
    128   Timer *T;
    129   TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION;
    130 public:
    131   explicit TimeRegion(Timer &t) : T(&t) {
    132     T->startTimer();
    133   }
    134   explicit TimeRegion(Timer *t) : T(t) {
    135     if (T) T->startTimer();
    136   }
    137   ~TimeRegion() {
    138     if (T) T->stopTimer();
    139   }
    140 };
    141 
    142 
    143 /// NamedRegionTimer - This class is basically a combination of TimeRegion and
    144 /// Timer.  It allows you to declare a new timer, AND specify the region to
    145 /// time, all in one statement.  All timers with the same name are merged.  This
    146 /// is primarily used for debugging and for hunting performance problems.
    147 ///
    148 struct NamedRegionTimer : public TimeRegion {
    149   explicit NamedRegionTimer(StringRef Name,
    150                             bool Enabled = true);
    151   explicit NamedRegionTimer(StringRef Name, StringRef GroupName,
    152                             bool Enabled = true);
    153 };
    154 
    155 
    156 /// The TimerGroup class is used to group together related timers into a single
    157 /// report that is printed when the TimerGroup is destroyed.  It is illegal to
    158 /// destroy a TimerGroup object before all of the Timers in it are gone.  A
    159 /// TimerGroup can be specified for a newly created timer in its constructor.
    160 ///
    161 class TimerGroup {
    162   std::string Name;
    163   Timer *FirstTimer;   // First timer in the group.
    164   std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
    165 
    166   TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
    167   TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
    168   void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
    169 public:
    170   explicit TimerGroup(StringRef name);
    171   ~TimerGroup();
    172 
    173   void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
    174 
    175   /// print - Print any started timers in this group and zero them.
    176   void print(raw_ostream &OS);
    177 
    178   /// printAll - This static method prints all timers and clears them all out.
    179   static void printAll(raw_ostream &OS);
    180 
    181 private:
    182   friend class Timer;
    183   void addTimer(Timer &T);
    184   void removeTimer(Timer &T);
    185   void PrintQueuedTimers(raw_ostream &OS);
    186 };
    187 
    188 } // End llvm namespace
    189 
    190 #endif
    191