summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/TimeProfiler.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2019-04-25 12:51:42 +0000
committerSam McCall <sam.mccall@gmail.com>2019-04-25 12:51:42 +0000
commita7edcfb533f34ffcb1fe0440e856f0966fb6b008 (patch)
tree6bd91cd2a6dd919700938e4046432eeff7035f62 /llvm/lib/Support/TimeProfiler.cpp
parent86ff9d313a8521dd715fa9a8c1e7c5f09589f6b1 (diff)
downloadbcm5719-llvm-a7edcfb533f34ffcb1fe0440e856f0966fb6b008.tar.gz
bcm5719-llvm-a7edcfb533f34ffcb1fe0440e856f0966fb6b008.zip
[Support] Add JSON streaming output API, faster where the heavy value types aren't needed.
Summary: There's still a little bit of constant factor that could be trimmed (e.g. more overloads to avoid round-tripping primitives through json::Value). But this solves the memory scaling problem, and greatly improves the performance constant factor, and the API should leave room for optimization if needed. Adapt TimeProfiler to use it, eliminating almost all the performance regression from r358476. Performance test on my machine: perf stat -r 5 ~/llvmbuild-opt/bin/clang++ -w -S -ftime-trace -mllvm -time-trace-granularity=0 spirit.cpp Handcrafted JSON (HEAD=r358532 with r358476 reverted): 2480ms json::Value (HEAD): 2757ms (+11%) After this patch: 2520 ms (+1.6%) Reviewers: anton-afanasyev, lebedev.ri Subscribers: kristina, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60804 llvm-svn: 359186
Diffstat (limited to 'llvm/lib/Support/TimeProfiler.cpp')
-rw-r--r--llvm/lib/Support/TimeProfiler.cpp69
1 files changed, 34 insertions, 35 deletions
diff --git a/llvm/lib/Support/TimeProfiler.cpp b/llvm/lib/Support/TimeProfiler.cpp
index 447ddf5ab3c..bc234081564 100644
--- a/llvm/lib/Support/TimeProfiler.cpp
+++ b/llvm/lib/Support/TimeProfiler.cpp
@@ -87,25 +87,24 @@ struct TimeTraceProfiler {
void Write(raw_pwrite_stream &OS) {
assert(Stack.empty() &&
"All profiler sections should be ended when calling Write");
-
- json::Array Events;
- const size_t ExpectedEntryCount =
- Entries.size() + CountAndTotalPerName.size() + 1;
- Events.reserve(ExpectedEntryCount);
+ json::OStream J(OS);
+ J.objectBegin();
+ J.attributeBegin("traceEvents");
+ J.arrayBegin();
// Emit all events for the main flame graph.
for (const auto &E : Entries) {
auto StartUs = duration_cast<microseconds>(E.Start - StartTime).count();
auto DurUs = duration_cast<microseconds>(E.Duration).count();
- Events.emplace_back(json::Object{
- {"pid", 1},
- {"tid", 0},
- {"ph", "X"},
- {"ts", StartUs},
- {"dur", DurUs},
- {"name", E.Name},
- {"args", json::Object{{"detail", E.Detail}}},
+ J.object([&]{
+ J.attribute("pid", 1);
+ J.attribute("tid", 0);
+ J.attribute("ph", "X");
+ J.attribute("ts", StartUs);
+ J.attribute("dur", DurUs);
+ J.attribute("name", E.Name);
+ J.attributeObject("args", [&] { J.attribute("detail", E.Detail); });
});
}
@@ -126,36 +125,36 @@ struct TimeTraceProfiler {
auto DurUs = duration_cast<microseconds>(E.second.second).count();
auto Count = CountAndTotalPerName[E.first].first;
- Events.emplace_back(json::Object{
- {"pid", 1},
- {"tid", Tid},
- {"ph", "X"},
- {"ts", 0},
- {"dur", DurUs},
- {"name", "Total " + E.first},
- {"args", json::Object{{"count", static_cast<int64_t>(Count)},
- {"avg ms",
- static_cast<int64_t>(DurUs / Count / 1000)}}},
+ J.object([&]{
+ J.attribute("pid", 1);
+ J.attribute("tid", Tid);
+ J.attribute("ph", "X");
+ J.attribute("ts", 0);
+ J.attribute("dur", DurUs);
+ J.attribute("name", "Total " + E.first);
+ J.attributeObject("args", [&] {
+ J.attribute("count", int64_t(Count));
+ J.attribute("avg ms", int64_t(DurUs / Count / 1000));
+ });
});
++Tid;
}
// Emit metadata event with process name.
- Events.emplace_back(json::Object{
- {"cat", ""},
- {"pid", 1},
- {"tid", 0},
- {"ts", 0},
- {"ph", "M"},
- {"name", "process_name"},
- {"args", json::Object{{"name", "clang"}}},
+ J.object([&] {
+ J.attribute("cat", "");
+ J.attribute("pid", 1);
+ J.attribute("tid", 0);
+ J.attribute("ts", 0);
+ J.attribute("ph", "M");
+ J.attribute("name", "process_name");
+ J.attributeObject("args", [&] { J.attribute("name", "clang"); });
});
- assert(Events.size() == ExpectedEntryCount && "Size prediction failed!");
-
- OS << formatv("{0:2}", json::Value(json::Object(
- {{"traceEvents", std::move(Events)}})));
+ J.arrayEnd();
+ J.attributeEnd();
+ J.objectEnd();
}
SmallVector<Entry, 16> Stack;
OpenPOWER on IntegriCloud