commit 7e8ee985e20f34ba6afb815a7cded443aca297d3 (tree)
parent f2cbc1912b9c58c2a20b9f32fb60b7793f5e4820
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date: Tue, 13 Jan 2026 19:10:45 -0500
tracy: add fiber integration
Diffstat:
4 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/build.zig b/build.zig
@@ -370,10 +370,20 @@ pub fn build(b: *std.Build) !void {
&[_][]const u8{ tracy_path, "public", "TracyClient.cpp" },
);
- const tracy_c_flags: []const []const u8 = &.{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" };
+ const tracy_c_flags: []const []const u8 = &.{
+ "-DTRACY_ENABLE=1",
+ "-fno-sanitize=undefined",
+ "-DTRACY_FIBERS",
+ };
exe.root_module.addIncludePath(.{ .cwd_relative = tracy_path });
- exe.root_module.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags });
+ exe.root_module.addCSourceFile(.{
+ .file = .{ .cwd_relative = client_cpp },
+ .flags = tracy_c_flags[0..switch (io_mode) {
+ .threaded => 2,
+ .evented => 3,
+ }],
+ });
exe.root_module.link_libc = true;
exe.root_module.link_libcpp = true;
diff --git a/lib/std/Io/IoUring.zig b/lib/std/Io/IoUring.zig
@@ -44,6 +44,14 @@ const timestampFromPosix = Io.Threaded.timestampFromPosix;
const unexpectedErrno = std.posix.unexpectedErrno;
const winsize = std.posix.winsize;
+const tracy = if (@hasDecl(@import("root"), "tracy")) @import("root").tracy else struct {
+ const enable = false;
+ inline fn fiberEnter(fiber: [*:0]const u8) void {
+ _ = fiber;
+ }
+ inline fn fiberLeave() void {}
+};
+
backing_allocator_needs_mutex: bool,
backing_allocator_mutex: Io.Mutex,
/// Does not need to be thread-safe if not used elsewhere.
@@ -90,6 +98,7 @@ const Thread = struct {
io_uring: IoUring,
idle_search_index: u32,
steal_ready_search_index: u32,
+ name_arena: if (tracy.enable) std.heap.ArenaAllocator.State else struct {},
csprng: Csprng,
threadlocal var self: ?*Thread = null;
@@ -138,6 +147,9 @@ const Fiber = struct {
},
cancel_status: CancelStatus,
cancel_protection: CancelProtection,
+ name: if (tracy.enable) [*:0]const u8 else void,
+
+ var next_name: u64 = 0;
const CancelStatus = packed struct(u32) {
requested: bool,
@@ -772,6 +784,7 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v
.status = .{ .queue_next = null },
.cancel_status = .unrequested,
.cancel_protection = .unblocked,
+ .name = if (tracy.enable) "main task",
};
const main_thread = &ev.threads.allocated[0];
Thread.self = main_thread;
@@ -802,11 +815,13 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v
),
.idle_search_index = 1,
.steal_ready_search_index = 1,
+ .name_arena = .{},
.csprng = .uninitialized,
};
errdefer main_thread.io_uring.deinit();
log.debug("created main idle {*}", .{&main_thread.idle_context});
log.debug("created main {*}", .{main_fiber});
+ if (tracy.enable) tracy.fiberEnter(main_fiber.name);
}
pub fn deinit(ev: *Evented) void {
@@ -958,6 +973,7 @@ fn schedule(ev: *Evented, thread: *Thread, ready_queue: Fiber.Queue) bool {
},
.idle_search_index = 0,
.steal_ready_search_index = 0,
+ .name_arena = .{},
.csprng = .uninitialized,
};
new_thread.thread = std.Thread.spawn(.{
@@ -1160,6 +1176,12 @@ const SwitchMessage = struct {
fn handle(message: *const SwitchMessage, ev: *Evented) void {
const thread: *Thread = .current();
thread.current_context = message.contexts.ready;
+ if (tracy.enable) {
+ if (message.contexts.ready != &thread.idle_context) {
+ const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.ready));
+ tracy.fiberEnter(fiber.name);
+ } else tracy.fiberLeave();
+ }
switch (message.pending_task) {
.nothing => {},
.reschedule => if (message.contexts.prev != &thread.idle_context) {
@@ -1543,6 +1565,17 @@ fn concurrent(
.status = .{ .queue_next = null },
.cancel_status = .unrequested,
.cancel_protection = .unblocked,
+ .name = if (tracy.enable) name: {
+ const thread: *Thread = .current();
+ var name_arena = thread.name_arena.promote(std.heap.page_allocator);
+ defer thread.name_arena = name_arena.state;
+ break :name std.fmt.allocPrintSentinel(
+ name_arena.allocator(),
+ "task {d}",
+ .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)},
+ 0,
+ ) catch return error.ConcurrencyUnavailable;
+ },
};
closure.* = .{
.ev = ev,
@@ -1920,6 +1953,17 @@ fn groupConcurrent(
.status = .{ .queue_next = null },
.cancel_status = .unrequested,
.cancel_protection = .unblocked,
+ .name = if (tracy.enable) name: {
+ const thread: *Thread = .current();
+ var name_arena = thread.name_arena.promote(std.heap.page_allocator);
+ defer thread.name_arena = name_arena.state;
+ break :name std.fmt.allocPrintSentinel(
+ name_arena.allocator(),
+ "group task {d}",
+ .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)},
+ 0,
+ ) catch return error.ConcurrencyUnavailable;
+ },
};
closure.* = .{
.ev = ev,
diff --git a/src/main.zig b/src/main.zig
@@ -21,7 +21,7 @@ const AstGen = std.zig.AstGen;
const ZonGen = std.zig.ZonGen;
const Server = std.zig.Server;
-const tracy = @import("tracy.zig");
+pub const tracy = @import("tracy.zig");
const Compilation = @import("Compilation.zig");
const link = @import("link.zig");
const Package = @import("Package.zig");
diff --git a/src/tracy.zig b/src/tracy.zig
@@ -98,6 +98,16 @@ pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name
}
}
+pub inline fn fiberEnter(fiber: [*:0]const u8) void {
+ if (!enable) return;
+ ___tracy_fiber_enter(fiber);
+}
+
+pub inline fn fiberLeave() void {
+ if (!enable) return;
+ ___tracy_fiber_leave();
+}
+
pub fn tracyAllocator(allocator: std.mem.Allocator) TracyAllocator(null) {
return TracyAllocator(null).init(allocator);
}
@@ -318,6 +328,8 @@ extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const anyopaque, depth
extern fn ___tracy_emit_logString(severity: MessageSeverity, color: i32, callstack_depth: i32, size: usize, txt: [*]const u8) void;
extern fn ___tracy_emit_logStringL(severity: MessageSeverity, color: i32, callstack_depth: i32, txt: [*:0]const u8) void;
extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void;
+extern fn ___tracy_fiber_enter(fiber: [*:0]const u8) void;
+extern fn ___tracy_fiber_leave() void;
const ___tracy_source_location_data = extern struct {
name: ?[*:0]const u8,