tangled
alpha
login
or
join now
altagos.dev
/
austin-converter
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
rework: austin frame storage
altagos.dev
8 months ago
15b8533f
812a65d7
verified
This commit was signed with the committer's
known signature
.
altagos.dev
SSH Key Fingerprint:
SHA256:UbTjEcCZlc6GzQWLCuDK3D//HESWD2xFPkzue9XMras=
+93
-56
2 changed files
expand all
collapse all
unified
split
src
austin.zig
main.zig
+81
-54
src/austin.zig
···
18
18
line_number: isize = 0,
19
19
};
20
20
21
21
+
pub const FrameID = usize;
22
22
+
21
23
pub const FrameWrapper = union(enum) {
22
22
-
call_stack: Frame,
24
24
+
frame: FrameID,
23
25
invalid: void,
24
26
gc: void,
25
27
};
···
47
49
full: Sample,
48
50
partial: PartialSample,
49
51
metric: Metric,
50
50
-
51
51
-
fn deinit(self: *SampleWrapper, allocator: mem.Allocator) void {
52
52
-
switch (self.*) {
53
53
-
.metric => {},
54
54
-
inline else => |*sample| {
55
55
-
for (sample.frames) |frame| {
56
56
-
switch (frame) {
57
57
-
.invalid, .gc => {},
58
58
-
.call_stack => |stack| {
59
59
-
allocator.free(stack.module);
60
60
-
allocator.free(stack.function);
61
61
-
},
62
62
-
}
63
63
-
}
64
64
-
allocator.free(sample.frames);
65
65
-
},
66
66
-
}
67
67
-
}
68
52
};
69
53
70
54
pub const Metadata = struct {
···
113
97
}
114
98
};
115
99
116
116
-
const MetadataFields = std.meta.FieldEnum(Metadata);
117
117
-
118
100
pub const Profile = struct {
119
101
meta: Metadata = .{},
102
102
+
frames: []Frame = undefined,
120
103
samples: []SampleWrapper = undefined,
121
121
-
_arena: mem.Allocator,
104
104
+
arena: mem.Allocator,
122
105
123
106
pub fn deinit(self: *Profile) void {
124
124
-
for (self.samples) |*sample| {
125
125
-
sample.deinit(self._arena);
107
107
+
for (self.frames) |frame| {
108
108
+
self.arena.free(frame.module);
109
109
+
self.arena.free(frame.function);
126
110
}
127
111
128
128
-
self._arena.free(self.samples);
112
112
+
for (self.samples) |sample| {
113
113
+
switch (sample) {
114
114
+
.metric => {},
115
115
+
inline else => |s| {
116
116
+
self.arena.free(s.frames);
117
117
+
},
118
118
+
}
119
119
+
}
120
120
+
121
121
+
self.arena.free(self.frames);
122
122
+
self.arena.free(self.samples);
123
123
+
}
124
124
+
125
125
+
pub fn getFrame(self: *const Profile, id: FrameID) ?Frame {
126
126
+
if (id < self.frames.len) {
127
127
+
return self.frames[id];
128
128
+
}
129
129
+
return null;
129
130
}
130
131
};
131
132
···
149
150
};
150
151
151
152
arena: mem.Allocator,
153
153
+
profile: Profile,
154
154
+
frames: std.ArrayList(Frame),
155
155
+
samples: std.ArrayList(SampleWrapper),
152
156
153
153
-
pub fn init(arena: mem.Allocator) Parser {
154
154
-
return .{ .arena = arena };
157
157
+
pub fn init(arena: mem.Allocator) !Parser {
158
158
+
return .{
159
159
+
.arena = arena,
160
160
+
.profile = .{ .arena = arena },
161
161
+
.frames = try .initCapacity(arena, 100),
162
162
+
.samples = try .initCapacity(arena, 1_000),
163
163
+
};
155
164
}
156
165
157
166
pub fn parse(self: *Parser, raw_reader: anytype, progress: *std.Progress.Node) !Profile {
167
167
+
defer self.samples.deinit();
168
168
+
defer self.frames.deinit();
169
169
+
158
170
var buffered_reader = std.io.bufferedReader(raw_reader);
159
171
var reader = buffered_reader.reader();
160
172
161
161
-
var profile = Profile{ ._arena = self.arena };
162
162
-
errdefer profile.deinit();
163
163
-
164
164
-
var samples: std.ArrayList(SampleWrapper) = try .initCapacity(self.arena, 1_000);
165
165
-
defer samples.deinit();
166
166
-
167
173
var reached_end: bool = false;
168
174
169
175
var line: std.ArrayList(u8) = .init(self.arena);
···
189
195
const key = it.next() orelse return error.MissingKey;
190
196
const value = mem.trimStart(u8, it.next() orelse return error.MissingValue, " ");
191
197
192
192
-
reached_end = profile.meta.parseField(key, value) catch |err| switch (err) {
198
198
+
reached_end = self.profile.meta.parseField(key, value) catch |err| switch (err) {
193
199
error.UnknownMetadataField => {
194
200
log.warn("Unknown metadata field: {s}", .{key});
195
201
continue;
···
211
217
std.process.exit(1);
212
218
};
213
219
214
214
-
try samples.append(sample);
220
220
+
try self.samples.append(sample);
215
221
}
216
222
}
217
223
218
218
-
profile.samples = try samples.toOwnedSlice();
219
219
-
return profile;
224
224
+
self.profile.frames = try self.frames.toOwnedSlice();
225
225
+
self.profile.samples = try self.samples.toOwnedSlice();
226
226
+
return self.profile;
220
227
}
221
228
222
229
const ParseSampleError = ParseError || mem.Allocator.Error || std.fmt.ParseIntError;
···
367
374
const module = frame.next() orelse return ParseError.NoModule;
368
375
369
376
if (mem.startsWith(u8, frame_raw, "::")) {
370
370
-
return FrameWrapper{ .call_stack = Frame{
371
371
-
.module = "",
372
372
-
.function = "",
373
373
-
.line_number = std.fmt.parseInt(isize, module, 0) catch
377
377
+
return try self.storeFrame(
378
378
+
"",
379
379
+
"",
380
380
+
std.fmt.parseInt(isize, module, 0) catch
374
381
return ParseError.InvalidLineNumber,
375
375
-
} };
382
382
+
);
376
383
}
377
384
378
385
if (mem.eql(u8, module, "GC"))
379
386
return FrameWrapper{ .gc = {} };
380
387
381
381
-
if (!mem.eql(u8, module, "INVALID")) {
382
382
-
const function = frame.next() orelse return ParseError.NoFunction;
388
388
+
if (mem.eql(u8, module, "INVALID"))
389
389
+
return FrameWrapper{ .invalid = {} };
383
390
384
384
-
const line_number = std.fmt.parseInt(
385
385
-
isize,
386
386
-
frame.next() orelse return ParseError.NoLineNumber,
387
387
-
0,
388
388
-
) catch return ParseError.InvalidLineNumber;
391
391
+
const function = frame.next() orelse return ParseError.NoFunction;
389
392
390
390
-
var f: Frame = .{ .line_number = line_number };
391
391
-
f.module = try self.arena.dupe(u8, module);
392
392
-
f.function = try self.arena.dupe(u8, function);
393
393
+
const line_number = std.fmt.parseInt(
394
394
+
isize,
395
395
+
frame.next() orelse return ParseError.NoLineNumber,
396
396
+
0,
397
397
+
) catch return ParseError.InvalidLineNumber;
393
398
394
394
-
return FrameWrapper{ .call_stack = f };
399
399
+
return try self.storeFrame(module, function, line_number);
400
400
+
}
401
401
+
402
402
+
fn storeFrame(
403
403
+
self: *Parser,
404
404
+
module: []const u8,
405
405
+
function: []const u8,
406
406
+
line_number: isize,
407
407
+
) !FrameWrapper {
408
408
+
var count: usize = 0;
409
409
+
for (self.frames.items, 0..) |*frame, id| {
410
410
+
if (mem.eql(u8, frame.module, module) and
411
411
+
mem.eql(u8, frame.function, function) and
412
412
+
frame.line_number == line_number)
413
413
+
{
414
414
+
return FrameWrapper{ .frame = id };
415
415
+
}
416
416
+
count += 1;
395
417
}
396
418
397
397
-
return FrameWrapper{ .invalid = {} };
419
419
+
var f: Frame = .{ .line_number = line_number };
420
420
+
f.module = try self.arena.dupe(u8, module);
421
421
+
f.function = try self.arena.dupe(u8, function);
422
422
+
423
423
+
try self.frames.append(f);
424
424
+
return FrameWrapper{ .frame = count + 1 };
398
425
}
399
426
};
+12
-2
src/main.zig
···
71
71
var progress = std.Progress.start(.{ .root_name = "Austin Converter" });
72
72
defer progress.end();
73
73
74
74
-
var parser: austin.austin.Parser = .init(allocator);
74
74
+
var parser: austin.austin.Parser = try .init(allocator);
75
75
var profile: austin.austin.Profile = undefined;
76
76
defer profile.deinit();
77
77
···
95
95
}
96
96
}
97
97
98
98
-
std.log.info("num samples: {} - meta: {}", .{ profile.samples.len, profile.meta });
98
98
+
for (profile.frames, 0..) |*frame, id| {
99
99
+
std.log.debug(
100
100
+
"Frame ID: {} => {{\n\tmodule = {s}\n\tfunction = {s}\n\tline number = {}\n}}\n",
101
101
+
.{ id, frame.module, frame.function, frame.line_number },
102
102
+
);
103
103
+
}
104
104
+
105
105
+
std.log.info(
106
106
+
"num samples: {} - num frames: {} - meta: {}",
107
107
+
.{ profile.samples.len, profile.frames.len, profile.meta },
108
108
+
);
99
109
}