authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-09-21 01:07:26 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-09-21 01:07:26 -07:00
log2c9c3f2ce69ec673df72ccad72efb15716dfb980
tree411e7db1a00710a72b76aaa28142c7b68f186749
parent3e61b8f598cfd209c142911db15077fb3e0ff1b7

add back spall backend printing the binary format


2 files changed, 151 insertions(+), 0 deletions(-)

src/mod.zig+1
......@@ -7,6 +7,7 @@ var started = false;
77pub const none = @import("./none.zig");
88pub const log = @import("./log.zig");
99pub const chrome = @import("./chrome.zig");
10pub const spall = @import("./spall.zig");
1011
1112pub fn init() !void {
1213 try impl.init();
src/spall.zig created+150
......@@ -0,0 +1,150 @@
1const std = @import("std");
2const tracer = @import("./mod.zig");
3const alloc = std.heap.c_allocator;
4const log = std.log.scoped(.tracer);
5const root = @import("root");
6const trim_count = root.build_options.src_file_trimlen;
7
8var pid: std.os.linux.pid_t = undefined;
9threadlocal var tid: std.os.linux.pid_t = undefined;
10threadlocal var path: []const u8 = undefined;
11threadlocal var file: std.fs.File = undefined;
12threadlocal var buffered_writer: std.io.BufferedWriter(4096, std.fs.File.Writer) = undefined;
13
14pub fn init() !void {
15 pid = std.os.linux.getpid();
16}
17
18pub fn deinit() void {
19 //
20}
21
22pub fn init_thread() !void {
23 tid = std.os.linux.gettid();
24
25 path = try std.fmt.allocPrint(alloc, "/data/trace.{d}.{d}.spall", .{ pid, tid });
26 file = try std.fs.cwd().createFile(path, .{});
27 buffered_writer = std.io.bufferedWriter(file.writer());
28
29 // try buffered_writer.writer().writeInt(u64, 0x0BADF00D, .Little);
30 try buffered_writer.writer().writeStruct(Header{
31 .magic = magic,
32 .version = 1,
33 .timestamp_unit = 1.0,
34 .must_be_0 = 0,
35 });
36}
37
38pub fn deinit_thread() void {
39 defer alloc.free(path);
40 defer file.close();
41
42 buffered_writer.flush() catch {};
43 log.debug("{s}", .{path});
44}
45
46pub inline fn trace_begin(ctx: tracer.Ctx) void {
47 buffered_writer.writer().writeStruct(BeginEvent{
48 .type = .begin,
49 .category = 0,
50 .pid = @intCast(pid),
51 .tid = @intCast(tid),
52 .time = @floatFromInt(std.time.microTimestamp()),
53 .name_len = @intCast(std.fmt.count("{s}:{d}:{d} ({s})", .{
54 if (ctx.src.file[0] == '/') ctx.src.file[trim_count..] else ctx.src.file,
55 ctx.src.line,
56 ctx.src.column,
57 ctx.src.fn_name,
58 })),
59 .args_len = 0,
60 }) catch return;
61 buffered_writer.writer().print("{s}:{d}:{d} ({s})", .{
62 if (ctx.src.file[0] == '/') ctx.src.file[trim_count..] else ctx.src.file,
63 ctx.src.line,
64 ctx.src.column,
65 ctx.src.fn_name,
66 }) catch return;
67}
68
69pub inline fn trace_end(ctx: tracer.Ctx) void {
70 _ = ctx;
71 buffered_writer.writer().writeStruct(EndEvent{
72 .type = .end,
73 .pid = @intCast(pid),
74 .tid = @intCast(tid),
75 .time = @floatFromInt(std.time.microTimestamp()),
76 }) catch return;
77}
78
79// https://github.com/colrdavidson/spall-web/blob/1d4610a1fe9aaaf2e071327a1142a498f3436bdc/formats/spall/spall.odin
80// https://github.com/colrdavidson/spall-web/blob/1d4610a1fe9aaaf2e071327a1142a498f3436bdc/tools/json2bin/json2bin.odin
81// https://github.com/colrdavidson/spall-web/blob/1d4610a1fe9aaaf2e071327a1142a498f3436bdc/tools/upconvert/main.odin
82
83// package spall
84
85// MAGIC :: u64(0x0BADF00D)
86const magic: u64 = 0x0BADF00D;
87
88// V1_Header :: struct #packed {
89// magic: u64,
90// version: u64,
91// timestamp_unit: f64,
92// must_be_0: u64,
93// }
94const Header = extern struct {
95 magic: u64 align(1),
96 version: u64 align(1),
97 timestamp_unit: f64 align(1),
98 must_be_0: u64 align(1),
99};
100
101// V1_Event_Type :: enum u8 {
102// Invalid = 0,
103// Custom_Data = 1, // Basic readers can skip this.
104// StreamOver = 2,
105// Begin = 3,
106// End = 4,
107// Instant = 5,
108// Overwrite_Timestamp = 6, // Retroactively change timestamp units - useful for incrementally improving RDTSC frequency.
109// }
110const EventType = enum(u8) {
111 invalid = 0,
112 custom_data = 1,
113 stream_over = 2,
114 begin = 3,
115 end = 4,
116 instant = 5,
117 overwrite_timestamp = 6,
118};
119
120// V1_Begin_Event :: struct #packed {
121// type: V1_Event_Type,
122// category: u8,
123// pid: u32,
124// tid: u32,
125// time: f64,
126// name_len: u8,
127// args_len: u8,
128// }
129const BeginEvent = extern struct {
130 type: EventType align(1),
131 category: u8 align(1),
132 pid: u32 align(1),
133 tid: u32 align(1),
134 time: f64 align(1),
135 name_len: u8 align(1),
136 args_len: u8 align(1),
137};
138
139// V1_End_Event :: struct #packed {
140// type: V1_Event_Type,
141// pid: u32,
142// tid: u32,
143// time: f64,
144// }
145const EndEvent = extern struct {
146 type: EventType align(1),
147 pid: u32 align(1),
148 tid: u32 align(1),
149 time: f64 align(1),
150};