tracing: wip i am going to regret not splitting this right now #1

Closed
jade wants to merge 4 commits from jade/meow into main AGit
7 changed files with 123779 additions and 0 deletions
Showing only changes of commit 8259d18368 - Show all commits

43
src/libtracing/main.cc Normal file
View file

@ -0,0 +1,43 @@
#include "trace-writer.hh"
#include <fstream>
#include <iostream>
using namespace nix::tracing;
class MyInternedRetriever : public InternedRetriever
{
virtual auto getName(InternedName idx) const -> std::string override
{
return "meow";
}
virtual auto getPos(InternedPos idx, std::string funcName) const -> TracePos override
{
return TracePos{
.fileName = "file.nix",
.functionName = "fun",
.lineNumber = 12,
};
}
public:
virtual ~MyInternedRetriever() = default;
};
int main(int argc, char **argv)
{
if (argc < 1) {
std::cerr << "provide filename pls\n";
return 1;
}
nix::tracing::TraceWriter tw{std::make_unique<MyInternedRetriever>()};
tw.begin(InternedPos{1}, InternedName{3}, Timestamp{250});
tw.end(Timestamp{1235});
std::ofstream ofs(argv[1]);
auto buf = tw.splat();
ofs.write(reinterpret_cast<const char *>(buf.data()), buf.size());
return 0;
}

View file

@ -0,0 +1 @@
// Intentionally empty (crbug.com/998165)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
libtracing_sources = files(
'trace-writer.cc',
'protozero_src/field.cc',
'protozero_src/gen_field_helpers.cc',
'protozero_src/message_arena.cc',
'protozero_src/message.cc',
'protozero_src/packed_repeated_fields.cc',
'protozero_src/proto_decoder.cc',
'protozero_src/scattered_heap_buffer.cc',
'protozero_src/scattered_stream_null_delegate.cc',
'protozero_src/scattered_stream_writer.cc',
'protozero_src/static_buffer.cc',
'protozero_src/virtual_destructors.cc',
)
subdir('perfetto/protozero')
libtracing_headers = [
protozero_headers,
files(
'trace-writer.hh',
),
]
libtracing = library(
'lixtracing',
libtracing_sources,
dependencies : [ ],
install : true,
# FIXME(Qyriad): is this right?
install_rpath : libdir,
cpp_args : [ '-DPERFETTO_DISABLE_LOG' ],
include_directories : include_directories('./perfetto/base/build_configs/bazel'),
)
liblixtracing = declare_dependency(
include_directories : include_directories('.'),
link_with : libtracing,
)
tracing_test = executable(
'lixtracingtest',
files('main.cc'),
dependencies : [ liblixtracing ],
install : false,
)

View file

@ -0,0 +1,190 @@
#include "meow/protos/perfetto/trace/perfetto_trace.pbzero.h"
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/message_handle.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/protozero/scattered_stream_writer.h"
#include "trace-writer.hh"
#include <memory>
#include <optional>
#include <unordered_map>
template<>
struct std::hash<nix::tracing::InternedPos>
{
size_t operator()(const nix::tracing::InternedPos p) const
{
return std::hash<uint32_t>()(p.key);
}
};
template<>
struct std::hash<nix::tracing::InternedName>
{
size_t operator()(const nix::tracing::InternedName p) const
{
return std::hash<uint32_t>()(p.key);
}
};
namespace nix::tracing {
using namespace perfetto::protos::pbzero;
struct ProtoInternedPos
{
uint32_t key;
explicit ProtoInternedPos(uint32_t key) : key(key) {}
ProtoInternedPos() = delete;
};
struct ProtoInternedName
{
uint32_t key;
explicit ProtoInternedName(uint32_t key) : key(key) {}
ProtoInternedName() = delete;
};
struct TraceWriter::Impl
{
std::unique_ptr<InternedRetriever> retriever_;
protozero::ScatteredHeapBuffer buf_;
protozero::ScatteredStreamWriter writer_;
protozero::MessageArena arena_;
Trace trace_;
protozero::MessageHandle<Trace> traceHandle_;
std::unordered_map<InternedPos, ProtoInternedPos> posMap_;
uint64_t posIid_ = 1;
std::unordered_map<InternedName, ProtoInternedName> nameMap_;
uint64_t nameIid_ = 1;
auto getName(InternedName name, std::optional<std::string> &outName) -> ProtoInternedName;
auto getPos(InternedPos pos, InternedName funcName, std::optional<TracePos> &outPos) -> ProtoInternedPos;
Impl(std::unique_ptr<InternedRetriever> retriever)
: retriever_(std::move(retriever))
, writer_(&this->buf_)
, traceHandle_(&this->trace_)
{
buf_.set_writer(&this->writer_);
trace_.Reset(&this->writer_, &this->arena_);
auto p = protozero::MessageHandle<TracePacket>(trace_.add_packet());
auto td = protozero::MessageHandle<TrackDescriptor>(p->set_track_descriptor());
td->set_name("track");
td->set_uuid(1);
p->set_trusted_packet_sequence_id(1337);
p->set_sequence_flags(perfetto_pbzero_enum_TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
p->set_previous_packet_dropped(true);
p->set_first_packet_on_sequence(true);
}
};
auto TraceWriter::Impl::getName(InternedName name, std::optional<std::string> &outName) -> ProtoInternedName
{
if (auto it = nameMap_.find(name); it != nameMap_.end()) {
// one already there, return it
return it->second;
} else {
auto nameStr = retriever_->getName(name);
outName = nameStr;
auto newIid = ++nameIid_;
nameMap_.insert(std::make_pair(name, newIid));
return ProtoInternedName(newIid);
}
}
auto TraceWriter::Impl::getPos(InternedPos pos, InternedName funcName, std::optional<TracePos> &outPos) -> ProtoInternedPos
{
if (auto it = posMap_.find(pos); it != posMap_.end()) {
// one already there, return it
return it->second;
} else {
auto nameRetrieved = retriever_->getName(funcName);
auto posResolved = retriever_->getPos(pos, nameRetrieved);
outPos = posResolved;
auto newIid = ++posIid_;
posMap_.insert(std::make_pair(pos, newIid));
return ProtoInternedPos(newIid);
}
}
TraceWriter::TraceWriter(std::unique_ptr<InternedRetriever> retriever)
: impl_(std::make_unique<Impl>(std::move(retriever)))
{
}
TraceWriter::~TraceWriter() = default;
void TraceWriter::begin(InternedPos pos, InternedName name, Timestamp ts)
{
std::optional<std::string> nameToIntern;
std::optional<TracePos> posToIntern;
auto nameIid = impl_->getName(name, nameToIntern);
auto posIid = impl_->getPos(pos, name, posToIntern);
auto packet = protozero::MessageHandle<TracePacket>(impl_->trace_.add_packet());
packet->set_sequence_flags(perfetto_pbzero_enum_TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
if (nameToIntern.has_value() || posToIntern.has_value()) {
auto internedData = protozero::MessageHandle<InternedData>(packet->set_interned_data());
if (nameToIntern.has_value()) {
auto evName = protozero::MessageHandle<EventName>(internedData->add_event_names());
evName->set_name(*nameToIntern);
evName->set_iid(nameIid.key);
}
if (posToIntern.has_value()) {
auto sourceLoc = protozero::MessageHandle<SourceLocation>(internedData->add_source_locations());
sourceLoc->set_iid(posIid.key);
sourceLoc->set_file_name(posToIntern->fileName);
sourceLoc->set_function_name(posToIntern->functionName);
sourceLoc->set_line_number(posToIntern->lineNumber);
}
}
packet->set_timestamp(ts.monotonic_nanos);
packet->set_trusted_packet_sequence_id(1337);
auto te = protozero::MessageHandle<TrackEvent>(packet->set_track_event());
te->set_type(perfetto_pbzero_enum_TrackEvent::TYPE_SLICE_BEGIN);
te->set_name_iid(nameIid.key);
te->set_source_location_iid(posIid.key);
// TODO: make a real value
te->set_track_uuid(1);
// te->set_name_iid(nameIid.key);
// te->set_name("meow");
// TODO: te->set_source_location_iid();
}
void TraceWriter::end(Timestamp ts)
{
protozero::MessageHandle<TracePacket> tp(impl_->trace_.add_packet());
tp->set_timestamp(ts.monotonic_nanos);
tp->set_trusted_packet_sequence_id(1337);
protozero::MessageHandle<TrackEvent> te(tp->set_track_event());
te->set_type(perfetto_pbzero_enum_TrackEvent::TYPE_SLICE_END);
te->set_track_uuid(1);
}
auto TraceWriter::splat() const -> std::vector<uint8_t>
{
impl_->traceHandle_->Finalize();
return impl_->buf_.StitchSlices();
}
}

View file

@ -0,0 +1,67 @@
#pragma once
///@file
#include <stddef.h>
#include <memory>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
namespace nix::tracing {
struct InternedPos
{
uint32_t key;
auto operator<=>(InternedPos const & other) const = default;
explicit InternedPos(uint32_t key) : key(key) {}
};
struct InternedName
{
uint32_t key;
auto operator<=>(InternedName const & other) const = default;
explicit InternedName(uint32_t key) : key(key) {}
};
struct Timestamp
{
uint64_t monotonic_nanos;
};
struct TracePos
{
std::string fileName;
std::string functionName;
uint32_t lineNumber;
};
/** Abstract class that retrieves information about things if they are not
* memoized already */
struct InternedRetriever
{
virtual auto getName(InternedName idx) const -> std::string = 0;
virtual auto getPos(InternedPos idx, std::string funcName) const -> TracePos = 0;
virtual ~InternedRetriever() = default;
};
class TraceWriter
{
struct Impl;
std::unique_ptr<Impl> impl_;
public:
TraceWriter(std::unique_ptr<InternedRetriever> retriever);
void begin(InternedPos pos, InternedName name, Timestamp ts);
void end(Timestamp ts);
/** Splats the trace out into a buffer */
auto splat() const -> std::vector<uint8_t>;
~TraceWriter();
};
}

View file

@ -5,6 +5,8 @@ subdir('libutil')
subdir('libstore') subdir('libstore')
# libfetchers depends on libstore # libfetchers depends on libstore
subdir('libfetchers') subdir('libfetchers')
# libtracing is self-contained
subdir('libtracing')
# libexpr depends on all of the above # libexpr depends on all of the above
subdir('libexpr') subdir('libexpr')
# libmain depends on libutil and libstore # libmain depends on libutil and libstore