Commit 94ada7db authored by Philip Trettner's avatar Philip Trettner

added export support for speedscope

parent 7244d964
......@@ -126,6 +126,14 @@ void visit_thread(visitor& v);
void write_json(std::string const& filename);
/// writes a csv where all trace points are summarized per-location
void write_summary_csv(std::string const& filename);
/// generates a Brendan Gregg's collapsed stack format file
/// see https://github.com/BrendanGregg/flamegraph#2-fold-stacks
/// e.g. for use with https://github.com/jlfwong/speedscope
/// recommended file name is .folded
void write_collapsed_stack(std::string const& filename);
/// Json file for use with https://github.com/jlfwong/speedscope
/// see https://github.com/jlfwong/speedscope/wiki/Importing-from-custom-sources
void write_speedscope_json(std::string const& filename);
/// writes various output formats to a given directory
/// NOTE: does nothing if directory does not exist
void write_dir(std::string const& path);
......
#include "Tracer.hh"
#include <algorithm>
#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>
#include <fstream>
......@@ -16,6 +18,175 @@ void write_dir(const std::string &path)
write_summary_csv(path + "/trace.csv");
}
void write_speedscope_json(std::string const &filename)
{
std::ofstream out(filename);
if (!out.good())
return;
struct event
{
char type;
int frame;
uint64_t at;
};
struct stack_entry
{
int frame;
};
struct visitor : tracing::visitor
{
uint64_t min_cycles = std::numeric_limits<uint64_t>::max();
uint64_t max_cycles = 0;
uint32_t last_cpu = 0;
std::unordered_map<location *, int> frames;
std::vector<location *> locations;
std::vector<stack_entry> stack;
std::vector<event> events;
std::thread::id thread;
int frame_of(location *loc)
{
auto it = frames.find(loc);
if (it != frames.end())
return it->second;
auto f = frames.size();
frames[loc] = f;
locations.push_back(loc);
return f;
}
virtual void on_thread(std::thread::id thread) override
{
close_pending_actions();
this->thread = thread;
stack.clear();
}
virtual void on_trace_start(tracing::location *loc, uint64_t cycles, uint32_t cpu) override
{
last_cpu = cpu;
min_cycles = std::min(min_cycles, cycles);
max_cycles = std::max(max_cycles, cycles);
auto f = frame_of(loc);
events.push_back({'O', f, cycles});
stack.push_back({f});
}
virtual void on_trace_end(uint64_t cycles, uint32_t cpu) override
{
last_cpu = cpu;
min_cycles = std::min(min_cycles, cycles);
max_cycles = std::max(max_cycles, cycles);
auto se = stack.back();
stack.pop_back();
events.push_back({'C', se.frame, cycles});
}
void close_pending_actions()
{
while (!stack.empty())
on_trace_end(max_cycles, last_cpu);
}
};
visitor v;
tracing::visit_thread(v);
v.close_pending_actions();
out << "{";
out << "\"version\":\"0.0.1\",";
out << "\"$schema\": \"https://www.speedscope.app/file-format-schema.json\",";
out << "\"shared\":{";
out << "\"frames\":[";
for (auto i = 0u; i < v.locations.size(); ++i)
{
auto loc = v.locations[i];
if (i > 0)
out << ",";
out << "{";
out << "\"name\":\"" << (std::string(loc->name).empty() ? loc->function : loc->name) << "\",";
out << "\"file\":\"" << loc->file << "\",";
out << "\"line\":" << loc->line << "";
out << "}";
}
out << "]";
out << "},";
out << "\"profiles\":[{";
out << "\"type\":\"evented\",";
out << "\"name\":\"Aion Trace\",";
out << "\"unit\":\"none\",";
out << "\"startValue\":0,";
out << "\"endValue\":" << v.max_cycles - v.min_cycles << ",";
out << "\"events\":[";
auto first = true;
for (auto const &e : v.events)
{
if (!first)
out << ",";
first = false;
out << "{";
out << "\"type\":\"" << e.type << "\",";
out << "\"frame\":" << e.frame << ",";
out << "\"at\":" << e.at - v.min_cycles;
out << "}";
}
out << "]";
out << "}]";
out << "}";
}
void write_collapsed_stack(std::string const &filename)
{
std::ofstream out(filename);
if (!out.good())
return;
std::cerr << "Not implemented" << std::endl;
/*
struct stack_entry
{
location *loc;
uint64_t cycles;
std::string prefix;
};
struct visitor : tracing::visitor
{
std::vector<stack_entry> stack;
std::thread::id thread;
virtual void on_thread(std::thread::id thread) override
{
this->thread = thread;
stack.clear();
// TODO: close pending actions
}
virtual void on_trace_start(tracing::location *loc, uint64_t cycles, uint32_t cpu) override
{
std::string name = loc->name;
std::string function = loc->function;
auto prefix = loc->name loc->function
//
stack.push_back({loc, cycles});
}
virtual void on_trace_end(uint64_t cycles, uint32_t cpu) override
{
auto se = stack.back();
stack.pop_back();
auto dt = cycles - se.cycles;
}
};
visitor v;
tracing::visit_thread(v);*/
}
void write_json(const std::string &filename)
{
std::ofstream out(filename);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment