Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Unified Diff: src/IceTimerTree.cpp

Issue 610813002: Subzero: Rewrite the pass timing infrastructure. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Make the optimized overlaps() implementation actually correct Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/IceTimerTree.cpp
diff --git a/src/IceTimerTree.cpp b/src/IceTimerTree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4bdb80ab91c34daeef2c439124d52c72f69353c5
--- /dev/null
+++ b/src/IceTimerTree.cpp
@@ -0,0 +1,142 @@
+//===- subzero/src/IceTimerTree.cpp - Pass timer defs ---------------------===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TimerTree class, which tracks flat and
+// cumulative execution time collection of call chains.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IceDefs.h"
+#include "IceTimerTree.h"
+
+namespace Ice {
+
+std::vector<IceString> TimerStack::IDs;
+
+TimerStack::TimerStack(const IceString &TopLevelName)
+ : FirstTimestamp(timestamp()), LastTimestamp(FirstTimestamp),
+ StateChangeCount(0), StackTop(0) {
+ Nodes.resize(1); // Reserve Nodes[0] for the root node.
+ push(getTimerID(TopLevelName));
+}
+
+// Returns the unique timer ID for the given Name, creating a new ID
+// if needed. For performance reasons, it's best to make only one
+// call per Name and cache the result, e.g. via a static initializer.
+TimerIdT TimerStack::getTimerID(const IceString &Name) {
+ TimerIdT Size = IDs.size();
+ for (TimerIdT i = 0; i < Size; ++i) {
+ if (IDs[i] == Name)
+ return i;
+ }
+ IDs.push_back(Name);
+ return Size;
+}
+
+// Pushes a new marker onto the timer stack.
+void TimerStack::push(TimerIdT ID) {
+ update();
+ if (Nodes[StackTop].Children.size() <= ID)
+ Nodes[StackTop].Children.resize(ID + 1);
+ if (Nodes[StackTop].Children[ID] == 0) {
+ TTindex Size = Nodes.size();
+ Nodes[StackTop].Children[ID] = Size;
+ Nodes.resize(Size + 1);
+ Nodes[Size].Parent = StackTop;
+ Nodes[Size].Interior = ID;
+ }
+ StackTop = Nodes[StackTop].Children[ID];
+}
+
+// Pop the top marker from the timer stack. Validates via assert()
+// that the expected marker is popped.
+void TimerStack::pop(TimerIdT ID) {
+ update();
+ assert(StackTop);
+ assert(Nodes[StackTop].Parent < StackTop);
+ // Verify that the expected ID is being popped.
+ assert(Nodes[StackTop].Interior == ID);
+ (void)ID;
+ // Verify that the parent's child points to the current stack top.
+ assert(Nodes[Nodes[StackTop].Parent].Children[ID] == StackTop);
+ StackTop = Nodes[StackTop].Parent;
+}
+
+// At a state change (e.g. push or pop), updates the flat and
+// cumulative timings for everything on the timer stack.
+void TimerStack::update() {
+ ++StateChangeCount;
+ // Whenever the stack is about to change, we grab the time delta
+ // since the last change and add it to all active cumulative
+ // elements and to the flat element for the top of the stack.
+ double Current = timestamp();
+ double Delta = Current - LastTimestamp;
+ LastTimestamp = Current;
+ if (StackTop) {
+ TimerIdT Leaf = Nodes[StackTop].Interior;
+ if (Leaf >= LeafTimes.size())
+ LeafTimes.resize(Leaf + 1);
+ LeafTimes[Leaf] += Delta;
+ }
+ TTindex Prefix = StackTop;
+ while (Prefix) {
+ Nodes[Prefix].Time += Delta;
+ TTindex Next = Nodes[Prefix].Parent;
+ assert(Next < Prefix);
+ Prefix = Next;
+ }
+}
+
+namespace {
+
+typedef std::multimap<double, IceString> DumpMapType;
+
+// Dump the Map items in reverse order of their time contribution.
+void dumpHelper(Ostream &Str, const DumpMapType &Map, double TotalTime) {
+ for (DumpMapType::const_reverse_iterator I = Map.rbegin(), E = Map.rend();
+ I != E; ++I) {
+ char buf[80];
+ snprintf(buf, llvm::array_lengthof(buf), " %10.6f (%4.1f%%): ", I->first,
+ I->first * 100 / TotalTime);
+ Str << buf << I->second << "\n";
+ }
+}
+
+} // end of anonymous namespace
+
+void TimerStack::dump(Ostream &Str) {
+ update();
+ double TotalTime = LastTimestamp - FirstTimestamp;
+ assert(TotalTime);
+ Str << "Cumulative function times:\n";
+ DumpMapType CumulativeMap;
+ for (TTindex i = 1; i < Nodes.size(); ++i) {
+ TTindex Prefix = i;
+ IceString Suffix = "";
+ while (Prefix) {
+ if (Suffix.empty())
+ Suffix = IDs[Nodes[Prefix].Interior];
+ else
+ Suffix = IDs[Nodes[Prefix].Interior] + "." + Suffix;
+ assert(Nodes[Prefix].Parent < Prefix);
+ Prefix = Nodes[Prefix].Parent;
+ }
+ CumulativeMap.insert(std::make_pair(Nodes[i].Time, Suffix));
+ }
+ dumpHelper(Str, CumulativeMap, TotalTime);
+ Str << "Flat function times:\n";
+ DumpMapType FlatMap;
+ for (TimerIdT i = 0; i < LeafTimes.size(); ++i) {
+ FlatMap.insert(std::make_pair(LeafTimes[i], IDs[i]));
+ }
+ dumpHelper(Str, FlatMap, TotalTime);
+ Str << "Number of timer updates: " << StateChangeCount << "\n";
+}
+
+} // end of namespace Ice
« src/IceOperand.cpp ('K') | « src/IceTimerTree.h ('k') | src/IceTranslator.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698