From f205fec78ae79707464d568bad297bc69fd1db78 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 9 May 2003 20:05:44 +0000 Subject: [PATCH] Add a new info-output-file option (hidden from --help) which is to be used by the testing scripts to avoid breaking diffs while still gathering stats. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6067 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Statistic.cpp | 28 +++--- lib/Support/Timer.cpp | 142 +++++++++++++++++++++--------- support/lib/Support/Statistic.cpp | 28 +++--- support/lib/Support/Timer.cpp | 142 +++++++++++++++++++++--------- 4 files changed, 236 insertions(+), 104 deletions(-) diff --git a/lib/Support/Statistic.cpp b/lib/Support/Statistic.cpp index f6645c6ae40..1141086c3f3 100644 --- a/lib/Support/Statistic.cpp +++ b/lib/Support/Statistic.cpp @@ -20,6 +20,9 @@ #include #include +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile(); + bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option unsigned StatisticBase::NumStats = 0; @@ -49,11 +52,12 @@ struct StatRecord { return std::strcmp(Name, SR.Name) < 0; } - void print(unsigned ValFieldSize, unsigned NameFieldSize) { - std::cerr << std::string(ValFieldSize-Value.length(), ' ') - << Value << " " << Name - << std::string(NameFieldSize-std::strlen(Name), ' ') - << " - " << Desc << "\n"; + void print(unsigned ValFieldSize, unsigned NameFieldSize, + std::ostream &OS) { + OS << std::string(ValFieldSize-Value.length(), ' ') + << Value << " " << Name + << std::string(NameFieldSize-std::strlen(Name), ' ') + << " - " << Desc << "\n"; } }; @@ -71,6 +75,8 @@ void StatisticBase::destroy() const { } if (--NumStats == 0 && AccumStats) { + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + // Figure out how long the biggest Value and Name fields are... unsigned MaxNameLen = 0, MaxValLen = 0; for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { @@ -84,18 +90,20 @@ void StatisticBase::destroy() const { std::stable_sort(AccumStats->begin(), AccumStats->end()); // Print out the statistics header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << " ... Statistics Collected ...\n" - << "===" << std::string(73, '-') << "===\n\n"; + *OutStream << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; // Print all of the statistics accumulated... for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) - (*AccumStats)[i].print(MaxValLen, MaxNameLen); + (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream); - std::cerr << std::endl; // Flush the output stream... + *OutStream << std::endl; // Flush the output stream... // Free all accumulated statistics... delete AccumStats; AccumStats = 0; + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } } diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index 62876539ff2..a013b46d12b 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -11,16 +11,23 @@ #include #include #include -#include #include #include #include +#include + +std::string LibSupportInfoOutputFilename; namespace { cl::opt TrackSpace("track-memory", cl::desc("Enable -time-passes memory " "tracking (this may be slow)"), cl::Hidden); + + cl::opt + InfoOutputFilename("info-output-file", + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(LibSupportInfoOutputFilename)); } static TimerGroup *DefaultTimerGroup = 0; @@ -161,37 +168,82 @@ void Timer::addPeakMemoryMeasurement() { // TimerGroup Implementation //===----------------------------------------------------------------------===// -static void printVal(double Val, double Total) { - if (Total < 1e-7) // Avoid dividing by zero... - fprintf(stderr, " ----- "); - else - fprintf(stderr, " %7.4f (%5.1f%%)", Val, Val*100/Total); +// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the +// TotalWidth size, and B is the AfterDec size. +// +static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth, + std::ostream &OS) { + assert(TotalWidth >= AfterDec+1 && "Bad FP Format!"); + OS.width(TotalWidth-AfterDec-1); + char OldFill = OS.fill(); + OS.fill(' '); + OS << (int)Val; // Integer part; + OS << "."; + OS.width(AfterDec); + OS.fill('0'); + unsigned ResultFieldSize = 1; + while (AfterDec--) ResultFieldSize *= 10; + OS << (int)(Val*ResultFieldSize) % ResultFieldSize; + OS.fill(OldFill); } -void Timer::print(const Timer &Total) { - if (Total.UserTime) - printVal(UserTime, Total.UserTime); - if (Total.SystemTime) - printVal(SystemTime, Total.SystemTime); - if (Total.getProcessTime()) - printVal(getProcessTime(), Total.getProcessTime()); - printVal(Elapsed, Total.Elapsed); - - fprintf(stderr, " "); - - if (Total.MemUsed) - fprintf(stderr, " %8ld ", MemUsed); - if (Total.PeakMem) { - if (PeakMem) - fprintf(stderr, " %8ld ", PeakMem); - else - fprintf(stderr, " "); +static void printVal(double Val, double Total, std::ostream &OS) { + if (Total < 1e-7) // Avoid dividing by zero... + OS << " ----- "; + else { + OS << " "; + printAlignedFP(Val, 4, 7, OS); + OS << " ("; + printAlignedFP(Val*100/Total, 1, 5, OS); + OS << "%)"; } - std::cerr << Name << "\n"; +} + +void Timer::print(const Timer &Total, std::ostream &OS) { + if (Total.UserTime) + printVal(UserTime, Total.UserTime, OS); + if (Total.SystemTime) + printVal(SystemTime, Total.SystemTime, OS); + if (Total.getProcessTime()) + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(Elapsed, Total.Elapsed, OS); + + OS << " "; + + if (Total.MemUsed) { + OS.width(9); + OS << MemUsed << " "; + } + if (Total.PeakMem) { + if (PeakMem) { + OS.width(9); + OS << PeakMem << " "; + } else + OS << " "; + } + OS << Name << "\n"; Started = false; // Once printed, don't print again } +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile() { + if (LibSupportInfoOutputFilename.empty()) + return &std::cerr; + if (LibSupportInfoOutputFilename == "-") + return &std::cout; + + std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(), + std::ios_base::app); + if (!Result->good()) { + std::cerr << "Error opening info-output-file '" + << LibSupportInfoOutputFilename << " for appending!\n"; + delete Result; + return &std::cerr; + } + return Result; +} + void TimerGroup::removeTimer() { if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report... @@ -203,6 +255,8 @@ void TimerGroup::removeTimer() { unsigned Padding = (80-Name.length())/2; if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + ++NumTimers; { // Scope to contain Total timer... don't allow total timer to drop us to // zero timers... @@ -212,38 +266,42 @@ void TimerGroup::removeTimer() { Total.sum(TimersToPrint[i]); // Print out timing header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << std::string(Padding, ' ') << Name << "\n" - << "===" << std::string(73, '-') - << "===\n Total Execution Time: "; + *OutStream << "===" << std::string(73, '-') << "===\n" + << std::string(Padding, ' ') << Name << "\n" + << "===" << std::string(73, '-') + << "===\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()); + printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream); + *OutStream << " seconds ("; + printAlignedFP(Total.getWallTime(), 4, 5, *OutStream); + *OutStream << " wall clock)\n\n"; if (Total.UserTime) - std::cerr << " ---User Time---"; + *OutStream << " ---User Time---"; if (Total.SystemTime) - std::cerr << " --System Time--"; + *OutStream << " --System Time--"; if (Total.getProcessTime()) - std::cerr << " --User+System--"; - std::cerr << " ---Wall Time---"; + *OutStream << " --User+System--"; + *OutStream << " ---Wall Time---"; if (Total.getMemUsed()) - std::cerr << " ---Mem---"; + *OutStream << " ---Mem---"; if (Total.getPeakMem()) - std::cerr << " -PeakMem-"; - std::cerr << " --- Name ---\n"; + *OutStream << " -PeakMem-"; + *OutStream << " --- Name ---\n"; // Loop through all of the timing data, printing it out... for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - TimersToPrint[i].print(Total); + TimersToPrint[i].print(Total, *OutStream); - Total.print(Total); - std::cerr << std::endl; // Flush output + Total.print(Total, *OutStream); + *OutStream << std::endl; // Flush output } --NumTimers; TimersToPrint.clear(); + + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } // Delete default timer group! diff --git a/support/lib/Support/Statistic.cpp b/support/lib/Support/Statistic.cpp index f6645c6ae40..1141086c3f3 100644 --- a/support/lib/Support/Statistic.cpp +++ b/support/lib/Support/Statistic.cpp @@ -20,6 +20,9 @@ #include #include +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile(); + bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option unsigned StatisticBase::NumStats = 0; @@ -49,11 +52,12 @@ struct StatRecord { return std::strcmp(Name, SR.Name) < 0; } - void print(unsigned ValFieldSize, unsigned NameFieldSize) { - std::cerr << std::string(ValFieldSize-Value.length(), ' ') - << Value << " " << Name - << std::string(NameFieldSize-std::strlen(Name), ' ') - << " - " << Desc << "\n"; + void print(unsigned ValFieldSize, unsigned NameFieldSize, + std::ostream &OS) { + OS << std::string(ValFieldSize-Value.length(), ' ') + << Value << " " << Name + << std::string(NameFieldSize-std::strlen(Name), ' ') + << " - " << Desc << "\n"; } }; @@ -71,6 +75,8 @@ void StatisticBase::destroy() const { } if (--NumStats == 0 && AccumStats) { + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + // Figure out how long the biggest Value and Name fields are... unsigned MaxNameLen = 0, MaxValLen = 0; for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { @@ -84,18 +90,20 @@ void StatisticBase::destroy() const { std::stable_sort(AccumStats->begin(), AccumStats->end()); // Print out the statistics header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << " ... Statistics Collected ...\n" - << "===" << std::string(73, '-') << "===\n\n"; + *OutStream << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; // Print all of the statistics accumulated... for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) - (*AccumStats)[i].print(MaxValLen, MaxNameLen); + (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream); - std::cerr << std::endl; // Flush the output stream... + *OutStream << std::endl; // Flush the output stream... // Free all accumulated statistics... delete AccumStats; AccumStats = 0; + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } } diff --git a/support/lib/Support/Timer.cpp b/support/lib/Support/Timer.cpp index 62876539ff2..a013b46d12b 100644 --- a/support/lib/Support/Timer.cpp +++ b/support/lib/Support/Timer.cpp @@ -11,16 +11,23 @@ #include #include #include -#include #include #include #include +#include + +std::string LibSupportInfoOutputFilename; namespace { cl::opt TrackSpace("track-memory", cl::desc("Enable -time-passes memory " "tracking (this may be slow)"), cl::Hidden); + + cl::opt + InfoOutputFilename("info-output-file", + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(LibSupportInfoOutputFilename)); } static TimerGroup *DefaultTimerGroup = 0; @@ -161,37 +168,82 @@ void Timer::addPeakMemoryMeasurement() { // TimerGroup Implementation //===----------------------------------------------------------------------===// -static void printVal(double Val, double Total) { - if (Total < 1e-7) // Avoid dividing by zero... - fprintf(stderr, " ----- "); - else - fprintf(stderr, " %7.4f (%5.1f%%)", Val, Val*100/Total); +// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the +// TotalWidth size, and B is the AfterDec size. +// +static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth, + std::ostream &OS) { + assert(TotalWidth >= AfterDec+1 && "Bad FP Format!"); + OS.width(TotalWidth-AfterDec-1); + char OldFill = OS.fill(); + OS.fill(' '); + OS << (int)Val; // Integer part; + OS << "."; + OS.width(AfterDec); + OS.fill('0'); + unsigned ResultFieldSize = 1; + while (AfterDec--) ResultFieldSize *= 10; + OS << (int)(Val*ResultFieldSize) % ResultFieldSize; + OS.fill(OldFill); } -void Timer::print(const Timer &Total) { - if (Total.UserTime) - printVal(UserTime, Total.UserTime); - if (Total.SystemTime) - printVal(SystemTime, Total.SystemTime); - if (Total.getProcessTime()) - printVal(getProcessTime(), Total.getProcessTime()); - printVal(Elapsed, Total.Elapsed); - - fprintf(stderr, " "); - - if (Total.MemUsed) - fprintf(stderr, " %8ld ", MemUsed); - if (Total.PeakMem) { - if (PeakMem) - fprintf(stderr, " %8ld ", PeakMem); - else - fprintf(stderr, " "); +static void printVal(double Val, double Total, std::ostream &OS) { + if (Total < 1e-7) // Avoid dividing by zero... + OS << " ----- "; + else { + OS << " "; + printAlignedFP(Val, 4, 7, OS); + OS << " ("; + printAlignedFP(Val*100/Total, 1, 5, OS); + OS << "%)"; } - std::cerr << Name << "\n"; +} + +void Timer::print(const Timer &Total, std::ostream &OS) { + if (Total.UserTime) + printVal(UserTime, Total.UserTime, OS); + if (Total.SystemTime) + printVal(SystemTime, Total.SystemTime, OS); + if (Total.getProcessTime()) + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(Elapsed, Total.Elapsed, OS); + + OS << " "; + + if (Total.MemUsed) { + OS.width(9); + OS << MemUsed << " "; + } + if (Total.PeakMem) { + if (PeakMem) { + OS.width(9); + OS << PeakMem << " "; + } else + OS << " "; + } + OS << Name << "\n"; Started = false; // Once printed, don't print again } +// GetLibSupportInfoOutputFile - Return a file stream to print our output on... +std::ostream *GetLibSupportInfoOutputFile() { + if (LibSupportInfoOutputFilename.empty()) + return &std::cerr; + if (LibSupportInfoOutputFilename == "-") + return &std::cout; + + std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(), + std::ios_base::app); + if (!Result->good()) { + std::cerr << "Error opening info-output-file '" + << LibSupportInfoOutputFilename << " for appending!\n"; + delete Result; + return &std::cerr; + } + return Result; +} + void TimerGroup::removeTimer() { if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report... @@ -203,6 +255,8 @@ void TimerGroup::removeTimer() { unsigned Padding = (80-Name.length())/2; if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + std::ostream *OutStream = GetLibSupportInfoOutputFile(); + ++NumTimers; { // Scope to contain Total timer... don't allow total timer to drop us to // zero timers... @@ -212,38 +266,42 @@ void TimerGroup::removeTimer() { Total.sum(TimersToPrint[i]); // Print out timing header... - std::cerr << "===" << std::string(73, '-') << "===\n" - << std::string(Padding, ' ') << Name << "\n" - << "===" << std::string(73, '-') - << "===\n Total Execution Time: "; + *OutStream << "===" << std::string(73, '-') << "===\n" + << std::string(Padding, ' ') << Name << "\n" + << "===" << std::string(73, '-') + << "===\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()); + printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream); + *OutStream << " seconds ("; + printAlignedFP(Total.getWallTime(), 4, 5, *OutStream); + *OutStream << " wall clock)\n\n"; if (Total.UserTime) - std::cerr << " ---User Time---"; + *OutStream << " ---User Time---"; if (Total.SystemTime) - std::cerr << " --System Time--"; + *OutStream << " --System Time--"; if (Total.getProcessTime()) - std::cerr << " --User+System--"; - std::cerr << " ---Wall Time---"; + *OutStream << " --User+System--"; + *OutStream << " ---Wall Time---"; if (Total.getMemUsed()) - std::cerr << " ---Mem---"; + *OutStream << " ---Mem---"; if (Total.getPeakMem()) - std::cerr << " -PeakMem-"; - std::cerr << " --- Name ---\n"; + *OutStream << " -PeakMem-"; + *OutStream << " --- Name ---\n"; // Loop through all of the timing data, printing it out... for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - TimersToPrint[i].print(Total); + TimersToPrint[i].print(Total, *OutStream); - Total.print(Total); - std::cerr << std::endl; // Flush output + Total.print(Total, *OutStream); + *OutStream << std::endl; // Flush output } --NumTimers; TimersToPrint.clear(); + + if (OutStream != &std::cerr && OutStream != &std::cout) + delete OutStream; // Close the file... } // Delete default timer group!