change TimerGroup to keep a linked list of active timers
authorChris Lattner <sabre@nondot.org>
Tue, 30 Mar 2010 04:40:01 +0000 (04:40 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 30 Mar 2010 04:40:01 +0000 (04:40 +0000)
instead of just a count of them, and refactor the guts of
report printing out of removeTimer into its own method.
Refactor addTimerToPrint away.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99872 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/Timer.h
lib/Support/Timer.cpp

index 59bab1d4741b775f1e93db51b787b32c0cb25108..aba31506fcf9e6c486a19f09c37874259c1649d6 100644 (file)
@@ -85,6 +85,8 @@ class Timer {
   std::string Name;      // The name of this time variable.
   bool Started;          // Has this time variable ever been started?
   TimerGroup *TG;        // The TimerGroup this Timer is in.
+  
+  Timer **Prev, *Next;   // Doubly linked list of timers in the group.
 public:
   explicit Timer(const std::string &N) : TG(0) { init(N); }
   Timer(const std::string &N, TimerGroup &tg) : TG(0) { init(N, tg); }
@@ -133,12 +135,10 @@ public:
     T->startTimer();
   }
   explicit TimeRegion(Timer *t) : T(t) {
-    if (T)
-      T->startTimer();
+    if (T) T->startTimer();
   }
   ~TimeRegion() {
-    if (T)
-      T->stopTimer();
+    if (T) T->stopTimer();
   }
 };
 
@@ -162,24 +162,36 @@ struct NamedRegionTimer : public TimeRegion {
 ///
 class TimerGroup {
   std::string Name;
-  unsigned NumTimers;
+  Timer *FirstTimer;   // First timer in the group.
   std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
 public:
-  explicit TimerGroup(const std::string &name) : Name(name), NumTimers(0) {}
-  explicit TimerGroup() : NumTimers(0) {}
+  explicit TimerGroup(const std::string &name) : Name(name), FirstTimer(0) {}
+  explicit TimerGroup() : FirstTimer(0) {}
+
+  explicit TimerGroup(const TimerGroup &TG) : FirstTimer(0) {
+    operator=(TG);
+  }
+
+  void operator=(const TimerGroup &TG) {
+    assert(TG.FirstTimer == 0 && FirstTimer == 0 &&
+           "Cannot assign group with timers");
+    Name = TG.Name;
+  }
+
   
   void setName(const std::string &name) { Name = name; }
   
   ~TimerGroup() {
-    assert(NumTimers == 0 &&
+    assert(FirstTimer == 0 &&
            "TimerGroup destroyed before all contained timers!");
   }
 
+  void PrintQueuedTimers(raw_ostream &OS);
+  
 private:
   friend class Timer;
-  void addTimer();
-  void removeTimer();
-  void addTimerToPrint(const TimeRecord &T, const std::string &Name);
+  void addTimer(Timer &T);
+  void removeTimer(Timer &T);
 };
 
 } // End llvm namespace
index 96f440a4ed4189bbb15aa14681c20c43170fc917..cc903805e8fa9f4a0ac63d978b646d7d57732a8a 100644 (file)
@@ -20,7 +20,6 @@
 #include "llvm/System/Mutex.h"
 #include "llvm/System/Process.h"
 #include "llvm/ADT/StringMap.h"
-#include <map>
 using namespace llvm;
 
 // GetLibSupportInfoOutputFile - Return a file stream to print our output on.
@@ -101,7 +100,7 @@ void Timer::init(const std::string &N) {
   Name = N;
   Started = false;
   TG = getDefaultTimerGroup();
-  TG->addTimer();
+  TG->addTimer(*this);
 }
 
 void Timer::init(const std::string &N, TimerGroup &tg) {
@@ -109,17 +108,12 @@ void Timer::init(const std::string &N, TimerGroup &tg) {
   Name = N;
   Started = false;
   TG = &tg;
-  TG->addTimer();
+  TG->addTimer(*this);
 }
 
 Timer::~Timer() {
   if (!TG) return;  // Never initialized.
-  
-  if (Started) {
-    Started = false;
-    TG->addTimerToPrint(Time, Name);
-  }
-  TG->removeTimer();
+  TG->removeTimer(*this);
 }
 
 static inline size_t getMemUsage() {
@@ -243,74 +237,92 @@ NamedRegionTimer::NamedRegionTimer(const std::string &Name,
 //   TimerGroup Implementation
 //===----------------------------------------------------------------------===//
 
-void TimerGroup::removeTimer() {
+void TimerGroup::removeTimer(Timer &T) {
   sys::SmartScopedLock<true> L(*TimerLock);
-  if (--NumTimers != 0 || TimersToPrint.empty())
-    return; // Don't print timing report.
   
-  // Sort the timers in descending order by amount of time taken.
-  std::sort(TimersToPrint.begin(), TimersToPrint.end());
+  // If the timer was started, move its data to TimersToPrint.
+  if (T.Started) {
+    T.Started = false;
+    TimersToPrint.push_back(std::make_pair(T.Time, T.Name));
+  }
+  
+  // Unlink the timer from our list.
+  *T.Prev = T.Next;
+  if (T.Next)
+    T.Next->Prev = T.Prev;
+  
+  // Print the report when all timers in this group are destroyed if some of
+  // them were started.
+  if (FirstTimer != 0 || TimersToPrint.empty())
+    return;
+  
+  raw_ostream *OutStream = GetLibSupportInfoOutputFile();
 
-  // Figure out how many spaces to indent TimerGroup name.
-  unsigned Padding = (80-Name.length())/2;
-  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
+  PrintQueuedTimers(*OutStream);
 
-  raw_ostream *OutStream = GetLibSupportInfoOutputFile();
+  if (OutStream != &errs() && OutStream != &outs())
+    delete OutStream;   // Close the file.
+}
+
+void TimerGroup::addTimer(Timer &T) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+  
+  // Add the timer to our list.
+  if (FirstTimer)
+    FirstTimer->Prev = &T.Next;
+  T.Next = FirstTimer;
+  T.Prev = &FirstTimer;
+  FirstTimer = &T;
+}
 
+void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
+  // Sort the timers in descending order by amount of time taken.
+  std::sort(TimersToPrint.begin(), TimersToPrint.end());
+  
   TimeRecord Total;
   for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
     Total += TimersToPrint[i].first;
-
+  
   // Print out timing header.
-  *OutStream << "===" << std::string(73, '-') << "===\n";
-  OutStream->indent(Padding) << Name << '\n';
-  *OutStream << "===" << std::string(73, '-') << "===\n";
-
+  OS << "===" << std::string(73, '-') << "===\n";
+  // Figure out how many spaces to indent TimerGroup name.
+  unsigned Padding = (80-Name.length())/2;
+  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
+  OS.indent(Padding) << Name << '\n';
+  OS << "===" << std::string(73, '-') << "===\n";
+  
   // If this is not an collection of ungrouped times, print the total time.
   // Ungrouped timers don't really make sense to add up.  We still print the
   // TOTAL line to make the percentages make sense.
   if (this != DefaultTimerGroup) {
-    *OutStream << "  Total Execution Time: ";
-    *OutStream << format("%5.4f", Total.getProcessTime()) << " seconds (";
-    *OutStream << format("%5.4f", Total.getWallTime()) << " wall clock)\n";
+    OS << "  Total Execution Time: ";
+    OS << format("%5.4f", Total.getProcessTime()) << " seconds (";
+    OS << format("%5.4f", Total.getWallTime()) << " wall clock)\n";
   }
-  *OutStream << "\n";
-
+  OS << '\n';
+  
   if (Total.getUserTime())
-    *OutStream << "   ---User Time---";
+    OS << "   ---User Time---";
   if (Total.getSystemTime())
-    *OutStream << "   --System Time--";
+    OS << "   --System Time--";
   if (Total.getProcessTime())
-    *OutStream << "   --User+System--";
-  *OutStream << "   ---Wall Time---";
+    OS << "   --User+System--";
+  OS << "   ---Wall Time---";
   if (Total.getMemUsed())
-    *OutStream << "  ---Mem---";
-  *OutStream << "  --- Name ---\n";
-
+    OS << "  ---Mem---";
+  OS << "  --- Name ---\n";
+  
   // Loop through all of the timing data, printing it out.
   for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
     const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
-    Entry.first.print(Total, *OutStream);
-    *OutStream << Entry.second << '\n';
+    Entry.first.print(Total, OS);
+    OS << Entry.second << '\n';
   }
-
-  Total.print(Total, *OutStream);
-  *OutStream << "Total\n\n";
-  OutStream->flush();
-
+  
+  Total.print(Total, OS);
+  OS << "Total\n\n";
+  OS.flush();
+  
   TimersToPrint.clear();
-
-  if (OutStream != &errs() && OutStream != &outs())
-    delete OutStream;   // Close the file.
-}
-
-void TimerGroup::addTimer() {
-  sys::SmartScopedLock<true> L(*TimerLock);
-  ++NumTimers;
-}
-
-void TimerGroup::addTimerToPrint(const TimeRecord &T, const std::string &Name) {
-  sys::SmartScopedLock<true> L(*TimerLock);
-  TimersToPrint.push_back(std::make_pair(T, Name));
 }