[llvm] r338834 - [XRay][tools] Use Support/JSON.h in llvm-xray convert

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 3 02:21:31 PDT 2018


Author: dberris
Date: Fri Aug  3 02:21:31 2018
New Revision: 338834

URL: http://llvm.org/viewvc/llvm-project?rev=338834&view=rev
Log:
[XRay][tools] Use Support/JSON.h in llvm-xray convert

Summary:
This change removes the ad-hoc implementation used by llvm-xray's
`convert` subcommand to generate JSON encoded catapult (AKA Chrome
Trace Viewer) trace output, to instead use the JSON encoder now in the
Support library.

Reviewers: kpw, zturner, eizan

Reviewed By: kpw

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D50129

Modified:
    llvm/trunk/tools/llvm-xray/xray-converter.cpp

Modified: llvm/trunk/tools/llvm-xray/xray-converter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-xray/xray-converter.cpp?rev=338834&r1=338833&r2=338834&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-xray/xray-converter.cpp (original)
+++ llvm/trunk/tools/llvm-xray/xray-converter.cpp Fri Aug  3 02:21:31 2018
@@ -18,6 +18,7 @@
 #include "llvm/Support/EndianStream.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
@@ -234,31 +235,6 @@ StackTrieNode *findOrCreateStackNode(
   return CurrentStack;
 }
 
-void writeTraceViewerRecord(uint16_t Version, raw_ostream &OS, int32_t FuncId,
-                            uint32_t TId, uint32_t PId, bool Symbolize,
-                            const FuncIdConversionHelper &FuncIdHelper,
-                            double EventTimestampUs,
-                            const StackTrieNode &StackCursor,
-                            StringRef FunctionPhenotype) {
-  OS << "    ";
-  if (Version >= 3) {
-    OS << llvm::formatv(
-        R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "{3}", )"
-        R"("ts" : "{4:f4}", "sf" : "{5}" })",
-        (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId)
-                   : llvm::to_string(FuncId)),
-        FunctionPhenotype, TId, PId, EventTimestampUs,
-        StackCursor.ExtraData.id);
-  } else {
-    OS << llvm::formatv(
-        R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "1", )"
-        R"("ts" : "{3:f3}", "sf" : "{4}" })",
-        (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId)
-                   : llvm::to_string(FuncId)),
-        FunctionPhenotype, TId, EventTimestampUs, StackCursor.ExtraData.id);
-  }
-}
-
 } // namespace
 
 void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records,
@@ -269,18 +245,14 @@ void TraceConverter::exportAsChromeTrace
 
   unsigned id_counter = 0;
 
-  OS << "{\n  \"traceEvents\": [";
   DenseMap<uint32_t, StackTrieNode *> StackCursorByThreadId{};
   DenseMap<uint32_t, SmallVector<StackTrieNode *, 4>> StackRootsByThreadId{};
   DenseMap<unsigned, StackTrieNode *> StacksByStackId{};
   std::forward_list<StackTrieNode> NodeStore{};
-  int loop_count = 0;
-  for (const auto &R : Records) {
-    if (loop_count++ == 0)
-      OS << "\n";
-    else
-      OS << ",\n";
 
+  // Create a JSON Array which will hold all trace events.
+  json::Array TraceEvents;
+  for (const auto &R : Records) {
     // Chrome trace event format always wants data in micros.
     // CyclesPerMicro = CycleHertz / 10^6
     // TSC / CyclesPerMicro == TSC * 10^6 / CycleHertz == MicroTimestamp
@@ -301,8 +273,15 @@ void TraceConverter::exportAsChromeTrace
       // type of B for begin or E for end, thread id, process id,
       // timestamp in microseconds, and a stack frame id. The ids are logged
       // in an id dictionary after the events.
-      writeTraceViewerRecord(Version, OS, R.FuncId, R.TId, R.PId, Symbolize,
-                             FuncIdHelper, EventTimestampUs, *StackCursor, "B");
+      TraceEvents.push_back(json::Object({
+          {"name", Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
+                             : llvm::to_string(R.FuncId)},
+          {"ph", "B"},
+          {"tid", llvm::to_string(R.TId)},
+          {"pid", llvm::to_string(Version >= 3 ? R.PId : 1)},
+          {"ts", llvm::formatv("{0:f4}", EventTimestampUs)},
+          {"sf", llvm::to_string(StackCursor->ExtraData.id)},
+      }));
       break;
     case RecordTypes::EXIT:
     case RecordTypes::TAIL_EXIT:
@@ -313,43 +292,51 @@ void TraceConverter::exportAsChromeTrace
       // (And/Or in loop termination below)
       StackTrieNode *PreviousCursor = nullptr;
       do {
-        if (PreviousCursor != nullptr) {
-          OS << ",\n";
-        }
-        writeTraceViewerRecord(Version, OS, StackCursor->FuncId, R.TId, R.PId,
-                               Symbolize, FuncIdHelper, EventTimestampUs,
-                               *StackCursor, "E");
+        TraceEvents.push_back(json::Object({
+            {"name", Symbolize
+                         ? FuncIdHelper.SymbolOrNumber(StackCursor->FuncId)
+                         : llvm::to_string(StackCursor->FuncId)},
+            {"ph", "E"},
+            {"tid", llvm::to_string(R.TId)},
+            {"pid", llvm::to_string(Version >= 3 ? R.PId : 1)},
+            {"ts", llvm::formatv("{0:f4}", EventTimestampUs)},
+            {"sf", llvm::to_string(StackCursor->ExtraData.id)},
+        }));
         PreviousCursor = StackCursor;
         StackCursor = StackCursor->Parent;
       } while (PreviousCursor->FuncId != R.FuncId && StackCursor != nullptr);
       break;
     }
   }
-  OS << "\n  ],\n"; // Close the Trace Events array.
-  OS << "  "
-     << "\"displayTimeUnit\": \"ns\",\n";
 
   // The stackFrames dictionary substantially reduces size of the output file by
   // avoiding repeating the entire call stack of function names for each entry.
-  OS << R"(  "stackFrames": {)";
-  int stack_frame_count = 0;
-  for (auto map_iter : StacksByStackId) {
-    if (stack_frame_count++ == 0)
-      OS << "\n";
-    else
-      OS << ",\n";
-    OS << "    ";
-    OS << llvm::formatv(
-        R"("{0}" : { "name" : "{1}")", map_iter.first,
-        (Symbolize ? FuncIdHelper.SymbolOrNumber(map_iter.second->FuncId)
-                   : llvm::to_string(map_iter.second->FuncId)));
-    if (map_iter.second->Parent != nullptr)
-      OS << llvm::formatv(R"(, "parent": "{0}")",
-                          map_iter.second->Parent->ExtraData.id);
-    OS << " }";
+  json::Object StackFrames;
+  for (const auto &Stack : StacksByStackId) {
+    const auto &StackId = Stack.first;
+    const auto &StackFunctionNode = Stack.second;
+    json::Object::iterator It;
+    std::tie(It, std::ignore) = StackFrames.insert({
+        llvm::to_string(StackId),
+        json::Object{
+            {"name",
+             Symbolize ? FuncIdHelper.SymbolOrNumber(StackFunctionNode->FuncId)
+                       : llvm::to_string(StackFunctionNode->FuncId)}},
+    });
+
+    if (StackFunctionNode->Parent != nullptr)
+      It->second.getAsObject()->insert(
+          {"parent", llvm::to_string(StackFunctionNode->Parent->ExtraData.id)});
   }
-  OS << "\n  }\n"; // Close the stack frames map.
-  OS << "}\n";     // Close the JSON entry.
+
+  json::Object TraceJSON{
+      {"displayTimeUnit", "ns"},
+      {"traceEvents", std::move(TraceEvents)},
+      {"stackFrames", std::move(StackFrames)},
+  };
+
+  // Pretty-print the JSON using two spaces for indentations.
+  OS << formatv("{0:2}", json::Value(std::move(TraceJSON)));
 }
 
 namespace llvm {




More information about the llvm-commits mailing list