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