mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-03-04 18:38:37 +00:00
Statistic/Timer: Include timers in PrintStatisticsJSON().
Differential Revision: https://reviews.llvm.org/D25588 llvm-svn: 287370
This commit is contained in:
parent
bcd40e41de
commit
643a05ab19
@ -165,7 +165,10 @@ void PrintStatistics();
|
||||
/// \brief Print statistics to the given output stream.
|
||||
void PrintStatistics(raw_ostream &OS);
|
||||
|
||||
/// Print statistics in JSON format.
|
||||
/// Print statistics in JSON format. This does include all global timers (\see
|
||||
/// Timer, TimerGroup). Note that the timers are cleared after printing and will
|
||||
/// not be printed in human readable form or in a second call of
|
||||
/// PrintStatisticsJSON().
|
||||
void PrintStatisticsJSON(raw_ostream &OS);
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -168,10 +168,24 @@ struct NamedRegionTimer : public TimeRegion {
|
||||
/// destroy a TimerGroup object before all of the Timers in it are gone. A
|
||||
/// TimerGroup can be specified for a newly created timer in its constructor.
|
||||
class TimerGroup {
|
||||
struct PrintRecord {
|
||||
TimeRecord Time;
|
||||
std::string Name;
|
||||
std::string Description;
|
||||
|
||||
PrintRecord(const PrintRecord &Other) = default;
|
||||
PrintRecord(const TimeRecord &Time, const std::string &Name,
|
||||
const std::string &Description)
|
||||
: Time(Time), Name(Name), Description(Description) {}
|
||||
|
||||
bool operator <(const PrintRecord &Other) const {
|
||||
return Time < Other.Time;
|
||||
}
|
||||
};
|
||||
std::string Name;
|
||||
std::string Description;
|
||||
Timer *FirstTimer = nullptr; ///< First timer in the group.
|
||||
std::vector<std::pair<TimeRecord, std::string>> TimersToPrint;
|
||||
std::vector<PrintRecord> TimersToPrint;
|
||||
|
||||
TimerGroup **Prev; ///< Pointer to Next field of previous timergroup in list.
|
||||
TimerGroup *Next; ///< Pointer to next timergroup in list.
|
||||
@ -193,11 +207,21 @@ public:
|
||||
/// This static method prints all timers and clears them all out.
|
||||
static void printAll(raw_ostream &OS);
|
||||
|
||||
/// Ensure global timer group lists are initialized. This function is mostly
|
||||
/// used by the Statistic code to influence the construction and destruction
|
||||
/// order of the global timer lists.
|
||||
static void ConstructTimerLists();
|
||||
private:
|
||||
friend class Timer;
|
||||
friend void PrintStatisticsJSON(raw_ostream &OS);
|
||||
void addTimer(Timer &T);
|
||||
void removeTimer(Timer &T);
|
||||
void prepareToPrintList();
|
||||
void PrintQueuedTimers(raw_ostream &OS);
|
||||
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
|
||||
const char *suffix, double Value);
|
||||
const char *printJSONValues(raw_ostream &OS, const char *delim);
|
||||
static const char *printAllJSONValues(raw_ostream &OS, const char *delim);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json 2>&1 | FileCheck %s --check-prefix=JSON
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json -info-output-file %t && FileCheck %s < %t --check-prefix=JSON
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json -time-passes 2>&1 | FileCheck %s --check-prefixes=JSON,JSONTIME
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json -time-passes -info-output-file %t && FileCheck %s < %t --check-prefixes=JSON,JSONTIME
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats 2>&1 | FileCheck %s --check-prefix=DEFAULT
|
||||
; RUN: opt < %s -o /dev/null -instsimplify -stats -info-output-file %t && FileCheck %s < %t --check-prefix=DEFAULT
|
||||
; REQUIRES: asserts
|
||||
|
||||
; JSON: {
|
||||
; JSON: "instsimplify.NumSimplified": 1
|
||||
; JSON-DAG: "instsimplify.NumSimplified": 1
|
||||
; JSONTIME-DAG: "time.pass.Remove redundant instructions.wall"
|
||||
; JSONTIME-DAG: "time.pass.Remove redundant instructions.user"
|
||||
; JSONTIME-DAG: "time.pass.Remove redundant instructions.sys"
|
||||
; JSON: }
|
||||
|
||||
; DEFAULT: 1 instsimplify - Number of redundant instructions removed
|
||||
|
Loading…
x
Reference in New Issue
Block a user