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: process info storage
altagos.dev
8 months ago
1e51f073
15b8533f
verified
This commit was signed with the committer's
known signature
.
altagos.dev
SSH Key Fingerprint:
SHA256:UbTjEcCZlc6GzQWLCuDK3D//HESWD2xFPkzue9XMras=
+124
-10
7 changed files
expand all
collapse all
unified
split
.tangled
workflows
build.yaml
.zed
tasks.json
build.zig.zon
scripts
install-zig.sh
src
austin.zig
main.zig
util.zig
+22
.tangled/workflows/build.yaml
···
1
1
+
when:
2
2
+
- event: ["push", "pull_request"]
3
3
+
branch: ["main"]
4
4
+
- event: ["manual"]
5
5
+
6
6
+
dependencies:
7
7
+
## from nixpkgs
8
8
+
nixpkgs:
9
9
+
- curl
10
10
+
- jq
11
11
+
- busybox
12
12
+
13
13
+
steps:
14
14
+
- name: "Install zig"
15
15
+
command: "./scripts/install-zig.sh"
16
16
+
- name: "Build ReleaseFast"
17
17
+
command: "./zig/zig build -Doptimize=ReleaseFast --summary all"
18
18
+
19
19
+
clone:
20
20
+
skip: false
21
21
+
depth: 1
22
22
+
submodules: true
+9
.zed/tasks.json
···
1
1
+
[
2
2
+
{
3
3
+
"label": "Build ReleaseFast",
4
4
+
"command": "zig build -Doptimize=ReleaseFast --summary all",
5
5
+
"use_new_terminal": false,
6
6
+
"allow_concurrent_runs": false,
7
7
+
"reveal": "always"
8
8
+
}
9
9
+
]
+2
-2
build.zig.zon
···
5
5
.minimum_zig_version = "0.15.0-dev.876+8eca338c2",
6
6
.dependencies = .{
7
7
.args = .{
8
8
-
.url = "git+https://github.com/ikskuh/zig-args?ref=master#9425b94c103a031777fdd272c555ce93a7dea581",
9
9
-
.hash = "args-0.0.0-CiLiqv_NAAC97fGpk9hS2K681jkiqPsWP6w3ucb_ctGH",
8
8
+
.url = "git+https://github.com/altagos/zig-args?ref=master#2d5a8debad37f8e0afbfcbf9c9b6f4a13a53f6aa",
9
9
+
.hash = "args-0.0.0-CiLiqjHPAAAbcho-tUvfMLs0mFvfzPESWdxHlHQ7Fhmp",
10
10
},
11
11
},
12
12
.paths = .{
+49
scripts/install-zig.sh
···
1
1
+
#!/bin/bash
2
2
+
3
3
+
JSON=$(curl -s https://ziglang.org/download/index.json)
4
4
+
5
5
+
# Determine the architecture:
6
6
+
if [ "$(uname -m)" = 'arm64' ] || [ "$(uname -m)" = 'aarch64' ]; then
7
7
+
ZIG_ARCH="aarch64"
8
8
+
else
9
9
+
ZIG_ARCH="x86_64"
10
10
+
fi
11
11
+
12
12
+
# Determine the operating system:
13
13
+
case "$(uname)" in
14
14
+
Linux)
15
15
+
ZIG_OS="linux"
16
16
+
;;
17
17
+
Darwin)
18
18
+
ZIG_OS="macos"
19
19
+
;;
20
20
+
CYGWIN*)
21
21
+
ZIG_OS="windows"
22
22
+
;;
23
23
+
*)
24
24
+
echo "Unknown OS"
25
25
+
exit 1
26
26
+
;;
27
27
+
esac
28
28
+
29
29
+
ZIG_TARGET="$ZIG_ARCH-$ZIG_OS"
30
30
+
31
31
+
URL=$(echo "$JSON" | jq -r ".master.\"$ZIG_TARGET\".tarball")
32
32
+
EXPECTED_SHA=$(echo "$JSON" | jq -r ".master.\"$ZIG_TARGET\".shasum")
33
33
+
34
34
+
curl -O "$URL"
35
35
+
36
36
+
ACTUAL_SHA=$(sha256sum zig*.tar.xz | awk '{print $1}')
37
37
+
if [ "$EXPECTED_SHA" != "$ACTUAL_SHA" ]; then
38
38
+
echo "SHA checksum verification failed."
39
39
+
echo "Expected: $EXPECTED_SHA"
40
40
+
echo "Actual: $ACTUAL_SHA"
41
41
+
exit 1
42
42
+
fi
43
43
+
44
44
+
if [ ! -d "zig" ]; then
45
45
+
mkdir zig
46
46
+
fi
47
47
+
48
48
+
tar -xf zig*.tar.xz -C zig --strip-components=1
49
49
+
rm zig*.tar.xz
+29
-4
src/austin.zig
···
12
12
tid: usize,
13
13
};
14
14
15
15
+
pub const ProcessID = usize;
16
16
+
15
17
pub const Frame = struct {
16
18
module: []const u8 = undefined,
17
19
function: []const u8 = undefined,
···
35
37
};
36
38
37
39
pub const Sample = struct {
38
38
-
process: Process,
40
40
+
process: ProcessID,
39
41
frames: []FrameWrapper,
40
42
metric: Metric,
41
43
};
42
44
43
45
pub const PartialSample = struct {
44
44
-
process: Process,
46
46
+
process: ProcessID,
45
47
frames: []FrameWrapper,
46
48
};
47
49
···
101
103
meta: Metadata = .{},
102
104
frames: []Frame = undefined,
103
105
samples: []SampleWrapper = undefined,
106
106
+
processes: []Process = undefined,
107
107
+
104
108
arena: mem.Allocator,
105
109
106
110
pub fn deinit(self: *Profile) void {
···
120
124
121
125
self.arena.free(self.frames);
122
126
self.arena.free(self.samples);
127
127
+
self.arena.free(self.processes);
123
128
}
124
129
125
130
pub fn getFrame(self: *const Profile, id: FrameID) ?Frame {
···
153
158
profile: Profile,
154
159
frames: std.ArrayList(Frame),
155
160
samples: std.ArrayList(SampleWrapper),
161
161
+
processes: std.ArrayList(Process),
156
162
157
163
pub fn init(arena: mem.Allocator) !Parser {
158
164
return .{
···
160
166
.profile = .{ .arena = arena },
161
167
.frames = try .initCapacity(arena, 100),
162
168
.samples = try .initCapacity(arena, 1_000),
169
169
+
.processes = try .initCapacity(arena, 1),
163
170
};
164
171
}
165
172
166
173
pub fn parse(self: *Parser, raw_reader: anytype, progress: *std.Progress.Node) !Profile {
167
174
defer self.samples.deinit();
168
175
defer self.frames.deinit();
176
176
+
defer self.processes.deinit();
169
177
170
178
var buffered_reader = std.io.bufferedReader(raw_reader);
171
179
var reader = buffered_reader.reader();
···
223
231
224
232
self.profile.frames = try self.frames.toOwnedSlice();
225
233
self.profile.samples = try self.samples.toOwnedSlice();
234
234
+
self.profile.processes = try self.processes.toOwnedSlice();
226
235
return self.profile;
227
236
}
228
237
···
331
340
// TID
332
341
const tid = thread.next() orelse return ParseError.NoTID;
333
342
334
334
-
sample.process = .{
343
343
+
sample.process = try self.storeProcess(.{
335
344
.pid = std.fmt.parseUnsigned(usize, pid[1..], 0) catch return ParseError.InvalidPID,
336
345
.iid = std.fmt.parseUnsigned(usize, iid[1..], 0) catch return ParseError.InvalidIID,
337
346
.tid = std.fmt.parseUnsigned(usize, tid, 0) catch return ParseError.InvalidTID,
338
338
-
};
347
347
+
});
339
348
340
349
// Frames
341
350
var frames: std.ArrayList(FrameWrapper) = try .initCapacity(self.arena, 1);
···
397
406
) catch return ParseError.InvalidLineNumber;
398
407
399
408
return try self.storeFrame(module, function, line_number);
409
409
+
}
410
410
+
411
411
+
fn storeProcess(
412
412
+
self: *Parser,
413
413
+
process: Process,
414
414
+
) !ProcessID {
415
415
+
var count: usize = 0;
416
416
+
for (self.processes.items, 0..) |*p, id| {
417
417
+
if (p.pid == process.pid and p.iid == process.iid and p.tid == process.tid) {
418
418
+
return id;
419
419
+
}
420
420
+
count += 1;
421
421
+
}
422
422
+
423
423
+
try self.processes.append(process);
424
424
+
return count + 1;
400
425
}
401
426
402
427
fn storeFrame(
+12
-3
src/main.zig
···
59
59
try args.printHelp(
60
60
Options,
61
61
Options.meta.name,
62
62
-
std.io.getStdOut().writer(),
62
62
+
std.fs.File.stderr().deprecatedWriter(),
63
63
);
64
64
return;
65
65
}
···
80
80
defer node.end();
81
81
82
82
if (opts.positionals.len == 0) {
83
83
-
profile = try parser.parse(std.io.getStdIn().reader(), &node);
83
83
+
profile = try parser.parse(std.fs.File.stdin().deprecatedReader(), &node);
84
84
} else {
85
85
const path = std.fs.cwd().realpathAlloc(allocator, opts.positionals[0]) catch |err| {
86
86
std.log.err("Invalid file path ({}): {s}", .{ err, opts.positionals[0] });
···
91
91
const file = try std.fs.openFileAbsolute(path, .{});
92
92
defer file.close();
93
93
94
94
-
profile = try parser.parse(file.reader(), &node);
94
94
+
profile = try parser.parse(file.deprecatedReader(), &node);
95
95
}
96
96
}
97
97
···
102
102
);
103
103
}
104
104
105
105
+
for (profile.processes, 0..) |*process, id| {
106
106
+
std.log.debug(
107
107
+
"Process ID: {} => {{\n\tPID = {}\n\tIID = {}\n\tTID = {}\n}}\n",
108
108
+
.{ id, process.pid, process.iid, process.tid },
109
109
+
);
110
110
+
}
111
111
+
105
112
std.log.info(
106
113
"num samples: {} - num frames: {} - meta: {}",
107
114
.{ profile.samples.len, profile.frames.len, profile.meta },
108
115
);
116
116
+
117
117
+
while (true) {}
109
118
}
+1
-1
src/util.zig
···
33
33
break :blk level_text ++ scope_prefix ++ "\x1b[90m \x1b[0m";
34
34
};
35
35
36
36
-
const stderr = std.io.getStdErr().writer();
36
36
+
const stderr = std.fs.File.stderr().deprecatedWriter();
37
37
var bw = std.io.bufferedWriter(stderr);
38
38
const writer = bw.writer();
39
39