diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Support/Statistic.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Support/Timer.cpp | 62 |
2 files changed, 67 insertions, 27 deletions
diff --git a/llvm/lib/Support/Statistic.cpp b/llvm/lib/Support/Statistic.cpp index d299bfcae46..0c50dfd27d6 100644 --- a/llvm/lib/Support/Statistic.cpp +++ b/llvm/lib/Support/Statistic.cpp @@ -29,7 +29,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" #include <algorithm> #include <cstring> using namespace llvm; @@ -60,6 +62,7 @@ class StatisticInfo { /// Sort statistics by debugtype,name,description. void sort(); public: + StatisticInfo(); ~StatisticInfo(); void addStatistic(const Statistic *S) { @@ -90,6 +93,11 @@ void Statistic::RegisterStatistic() { } } +StatisticInfo::StatisticInfo() { + // Ensure timergroup lists are created first so they are destructed after us. + TimerGroup::ConstructTimerLists(); +} + // Print information when destroyed, iff command line option is specified. StatisticInfo::~StatisticInfo() { if (::Stats || PrintOnExit) @@ -148,17 +156,6 @@ void llvm::PrintStatistics(raw_ostream &OS) { OS.flush(); } -static void write_json_string_escaped(raw_ostream &OS, const char *string) { - // Out current usage should not need any escaping. Keep it simple and just - // check that the input is pure ASCII without special characers. -#ifndef NDEBUG - for (const unsigned char *c = (const unsigned char*)string; *c != '\0'; ++c) { - assert(*c != '\\' && *c != '\"' && *c >= 0x20 && *c < 0x80); - } -#endif - OS << string; -} - void llvm::PrintStatisticsJSON(raw_ostream &OS) { StatisticInfo &Stats = *StatInfo; @@ -169,13 +166,16 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) { const char *delim = ""; for (const Statistic *Stat : Stats.Stats) { OS << delim; - OS << "\t\""; - write_json_string_escaped(OS, Stat->getDebugType()); - OS << '.'; - write_json_string_escaped(OS, Stat->getName()); - OS << "\": " << Stat->getValue(); + assert(!yaml::needsQuotes(Stat->getDebugType()) && + "Statistic group/type name is simple."); + assert(!yaml::needsQuotes(Stat->getName()) && "Statistic name is simple"); + OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": " + << Stat->getValue(); delim = ",\n"; } + // Print timers. + TimerGroup::printAllJSONValues(OS, delim); + OS << "\n}\n"; OS.flush(); } diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp index cca538c3d25..fbd73d0b6b3 100644 --- a/llvm/lib/Support/Timer.cpp +++ b/llvm/lib/Support/Timer.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/Mutex.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" using namespace llvm; // This ugly hack is brought to you courtesy of constructor/destructor ordering @@ -260,7 +261,7 @@ void TimerGroup::removeTimer(Timer &T) { // If the timer was started, move its data to TimersToPrint. if (T.hasTriggered()) - TimersToPrint.emplace_back(T.Time, T.Description); + TimersToPrint.emplace_back(T.Time, T.Name, T.Description); T.TG = nullptr; @@ -294,8 +295,8 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { std::sort(TimersToPrint.begin(), TimersToPrint.end()); TimeRecord Total; - for (auto &RecordNamePair : TimersToPrint) - Total += RecordNamePair.first; + for (const PrintRecord &Record : TimersToPrint) + Total += Record.Time; // Print out timing header. OS << "===" << std::string(73, '-') << "===\n"; @@ -325,10 +326,10 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { 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, OS); - OS << Entry.second << '\n'; + for (const PrintRecord &Record : make_range(TimersToPrint.rbegin(), + TimersToPrint.rend())) { + Record.Time.print(Total, OS); + OS << Record.Description << '\n'; } Total.print(Total, OS); @@ -338,18 +339,22 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { TimersToPrint.clear(); } -void TimerGroup::print(raw_ostream &OS) { - sys::SmartScopedLock<true> L(*TimerLock); - +void TimerGroup::prepareToPrintList() { // See if any of our timers were started, if so add them to TimersToPrint and // reset them. for (Timer *T = FirstTimer; T; T = T->Next) { if (!T->hasTriggered()) continue; - TimersToPrint.emplace_back(T->Time, T->Description); + TimersToPrint.emplace_back(T->Time, T->Name, T->Description); // Clear out the time. T->clear(); } +} + +void TimerGroup::print(raw_ostream &OS) { + sys::SmartScopedLock<true> L(*TimerLock); + + prepareToPrintList(); // If any timers were started, print the group. if (!TimersToPrint.empty()) @@ -362,3 +367,38 @@ void TimerGroup::printAll(raw_ostream &OS) { for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) TG->print(OS); } + +void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R, + const char *suffix, double Value) { + assert(!yaml::needsQuotes(Name) && "TimerGroup name needs no quotes"); + assert(!yaml::needsQuotes(R.Name) && "Timer name needs no quotes"); + OS << "\t\"time." << Name << '.' << R.Name << suffix << "\": " << Value; +} + +const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) { + prepareToPrintList(); + for (const PrintRecord &R : TimersToPrint) { + OS << delim; + delim = ",\n"; + + const TimeRecord &T = R.Time; + printJSONValue(OS, R, ".wall", T.getWallTime()); + OS << delim; + printJSONValue(OS, R, ".user", T.getUserTime()); + OS << delim; + printJSONValue(OS, R, ".sys", T.getSystemTime()); + } + TimersToPrint.clear(); + return delim; +} + +const char *TimerGroup::printAllJSONValues(raw_ostream &OS, const char *delim) { + sys::SmartScopedLock<true> L(*TimerLock); + for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) + delim = TG->printJSONValues(OS, delim); + return delim; +} + +void TimerGroup::ConstructTimerLists() { + (void)*NamedGroupedTimers; +} |