From: Chris Lattner Date: Tue, 30 Mar 2010 04:40:01 +0000 (+0000) Subject: change TimerGroup to keep a linked list of active timers X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b9312690a2a79de490ab9c439b9b5d7c9319bff8;p=oota-llvm.git change TimerGroup to keep a linked list of active timers 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 --- diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 59bab1d4741..aba31506fcf 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -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 > 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 diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index 96f440a4ed4..cc903805e8f 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -20,7 +20,6 @@ #include "llvm/System/Mutex.h" #include "llvm/System/Process.h" #include "llvm/ADT/StringMap.h" -#include 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 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 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 &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 L(*TimerLock); - ++NumTimers; -} - -void TimerGroup::addTimerToPrint(const TimeRecord &T, const std::string &Name) { - sys::SmartScopedLock L(*TimerLock); - TimersToPrint.push_back(std::make_pair(T, Name)); }