X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=support%2Flib%2FSupport%2FTimer.cpp;h=62876539ff2664d3c67e57e7abf1ee1907f8b144;hb=8166b7cdb891e0d3c5789260248211a8b6e99787;hp=48b8f57c3fe5fe05fe27ca8d1351e629c3fa1b79;hpb=6cd11f6535600da5f286056748d4817e0f44b778;p=oota-llvm.git diff --git a/support/lib/Support/Timer.cpp b/support/lib/Support/Timer.cpp index 48b8f57c3fe..62876539ff2 100644 --- a/support/lib/Support/Timer.cpp +++ b/support/lib/Support/Timer.cpp @@ -5,6 +5,7 @@ //===----------------------------------------------------------------------===// #include "Support/Timer.h" +#include "Support/CommandLine.h" #include #include #include @@ -15,6 +16,13 @@ #include #include +namespace { + cl::opt + TrackSpace("track-memory", cl::desc("Enable -time-passes memory " + "tracking (this may be slow)"), + cl::Hidden); +} + static TimerGroup *DefaultTimerGroup = 0; static TimerGroup *getDefaultTimerGroup() { if (DefaultTimerGroup) return DefaultTimerGroup; @@ -22,13 +30,13 @@ static TimerGroup *getDefaultTimerGroup() { } Timer::Timer(const std::string &N) - : Elapsed(0), UserTime(0), SystemTime(0), MaxRSS(0), Name(N), + : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), Started(false), TG(getDefaultTimerGroup()) { TG->addTimer(); } Timer::Timer(const std::string &N, TimerGroup &tg) - : Elapsed(0), UserTime(0), SystemTime(0), MaxRSS(0), Name(N), + : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), Started(false), TG(&tg) { TG->addTimer(); } @@ -58,60 +66,97 @@ Timer::~Timer() { } } +static long getMemUsage() { + if (TrackSpace) { + struct mallinfo MI = mallinfo(); + return MI.uordblks/*+MI.hblkhd*/; + } else { + return 0; + } +} + struct TimeRecord { double Elapsed, UserTime, SystemTime; - unsigned long MaxRSS; + long MemUsed; }; -static TimeRecord getTimeRecord() { +static TimeRecord getTimeRecord(bool Start) { struct rusage RU; struct timeval T; + long MemUsed = 0; + if (Start) { + MemUsed = getMemUsage(); + if (getrusage(RUSAGE_SELF, &RU)) + perror("getrusage call failed: -time-passes info incorrect!"); + } gettimeofday(&T, 0); - if (getrusage(RUSAGE_SELF, &RU)) { - perror("getrusage call failed: -time-passes info incorrect!"); + + if (!Start) { + MemUsed = getMemUsage(); + if (getrusage(RUSAGE_SELF, &RU)) + perror("getrusage call failed: -time-passes info incorrect!"); } TimeRecord Result; Result.Elapsed = T.tv_sec + T.tv_usec/1000000.0; Result.UserTime = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0; Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0; - -#ifndef __sparc__ - struct mallinfo MI = mallinfo(); - Result.MaxRSS = MI.uordblks; -#else - Result.MaxRSS = 0; -#endif + Result.MemUsed = MemUsed; return Result; } +static std::vector ActiveTimers; + void Timer::startTimer() { Started = true; - TimeRecord TR = getTimeRecord(); + TimeRecord TR = getTimeRecord(true); Elapsed -= TR.Elapsed; UserTime -= TR.UserTime; SystemTime -= TR.SystemTime; - MaxRSS -= TR.MaxRSS; + MemUsed -= TR.MemUsed; + PeakMemBase = TR.MemUsed; + ActiveTimers.push_back(this); } void Timer::stopTimer() { - TimeRecord TR = getTimeRecord(); + TimeRecord TR = getTimeRecord(false); Elapsed += TR.Elapsed; UserTime += TR.UserTime; SystemTime += TR.SystemTime; - MaxRSS += TR.MaxRSS; - if ((signed long)MaxRSS < 0) - MaxRSS = 0; + MemUsed += TR.MemUsed; + + if (ActiveTimers.back() == this) { + ActiveTimers.pop_back(); + } else { + std::vector::iterator I = + std::find(ActiveTimers.begin(), ActiveTimers.end(), this); + assert(I != ActiveTimers.end() && "stop but no startTimer?"); + ActiveTimers.erase(I); + } } void Timer::sum(const Timer &T) { Elapsed += T.Elapsed; UserTime += T.UserTime; SystemTime += T.SystemTime; - MaxRSS += T.MaxRSS; + MemUsed += T.MemUsed; + PeakMem += T.PeakMem; +} + +/// addPeakMemoryMeasurement - This method should be called whenever memory +/// usage needs to be checked. It adds a peak memory measurement to the +/// currently active timers, which will be printed when the timer group prints +/// +void Timer::addPeakMemoryMeasurement() { + long MemUsed = getMemUsage(); + + for (std::vector::iterator I = ActiveTimers.begin(), + E = ActiveTimers.end(); I != E; ++I) + (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase); } + //===----------------------------------------------------------------------===// // TimerGroup Implementation //===----------------------------------------------------------------------===// @@ -134,8 +179,14 @@ void Timer::print(const Timer &Total) { fprintf(stderr, " "); - if (Total.MaxRSS) - fprintf(stderr, " %8ld ", MaxRSS); + if (Total.MemUsed) + fprintf(stderr, " %8ld ", MemUsed); + if (Total.PeakMem) { + if (PeakMem) + fprintf(stderr, " %8ld ", PeakMem); + else + fprintf(stderr, " "); + } std::cerr << Name << "\n"; Started = false; // Once printed, don't print again @@ -164,9 +215,11 @@ void TimerGroup::removeTimer() { std::cerr << "===" << std::string(73, '-') << "===\n" << std::string(Padding, ' ') << Name << "\n" << "===" << std::string(73, '-') - << "===\n Total Execution Time: " << Total.getProcessTime() - << " seconds (" << Total.getWallTime() - << " wall clock)\n\n"; + << "===\n Total Execution Time: "; + + // Hack for GCC 2.96... :( it doesn't support manipulators! + fprintf(stderr, "%.4f seconds (%.4f wall clock)\n\n", + Total.getProcessTime(), Total.getWallTime()); if (Total.UserTime) std::cerr << " ---User Time---"; @@ -175,9 +228,10 @@ void TimerGroup::removeTimer() { if (Total.getProcessTime()) std::cerr << " --User+System--"; std::cerr << " ---Wall Time---"; - - if (Total.getMaxRSS()) + if (Total.getMemUsed()) std::cerr << " ---Mem---"; + if (Total.getPeakMem()) + std::cerr << " -PeakMem-"; std::cerr << " --- Name ---\n"; // Loop through all of the timing data, printing it out...