authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-01-13 19:10:45-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-02-09 10:47:21-05:00
log7e8ee985e20f34ba6afb815a7cded443aca297d3
treedf089878f2f2360f26eae2cd847aa17f2d6fdb85
parentf2cbc1912b9c58c2a20b9f32fb60b7793f5e4820

tracy: add fiber integration


4 files changed, 69 insertions(+), 3 deletions(-)

build.zig+12-2
......@@ -370,10 +370,20 @@ pub fn build(b: *std.Build) !void {
370370 &[_][]const u8{ tracy_path, "public", "TracyClient.cpp" },
371371 );
372372
373 const tracy_c_flags: []const []const u8 = &.{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" };
373 const tracy_c_flags: []const []const u8 = &.{
374 "-DTRACY_ENABLE=1",
375 "-fno-sanitize=undefined",
376 "-DTRACY_FIBERS",
377 };
374378
375379 exe.root_module.addIncludePath(.{ .cwd_relative = tracy_path });
376 exe.root_module.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags });
380 exe.root_module.addCSourceFile(.{
381 .file = .{ .cwd_relative = client_cpp },
382 .flags = tracy_c_flags[0..switch (io_mode) {
383 .threaded => 2,
384 .evented => 3,
385 }],
386 });
377387 exe.root_module.link_libc = true;
378388 exe.root_module.link_libcpp = true;
379389
lib/std/Io/IoUring.zig+44
......@@ -44,6 +44,14 @@ const timestampFromPosix = Io.Threaded.timestampFromPosix;
4444const unexpectedErrno = std.posix.unexpectedErrno;
4545const winsize = std.posix.winsize;
4646
47const tracy = if (@hasDecl(@import("root"), "tracy")) @import("root").tracy else struct {
48 const enable = false;
49 inline fn fiberEnter(fiber: [*:0]const u8) void {
50 _ = fiber;
51 }
52 inline fn fiberLeave() void {}
53};
54
4755backing_allocator_needs_mutex: bool,
4856backing_allocator_mutex: Io.Mutex,
4957/// Does not need to be thread-safe if not used elsewhere.
......@@ -90,6 +98,7 @@ const Thread = struct {
9098 io_uring: IoUring,
9199 idle_search_index: u32,
92100 steal_ready_search_index: u32,
101 name_arena: if (tracy.enable) std.heap.ArenaAllocator.State else struct {},
93102 csprng: Csprng,
94103
95104 threadlocal var self: ?*Thread = null;
......@@ -138,6 +147,9 @@ const Fiber = struct {
138147 },
139148 cancel_status: CancelStatus,
140149 cancel_protection: CancelProtection,
150 name: if (tracy.enable) [*:0]const u8 else void,
151
152 var next_name: u64 = 0;
141153
142154 const CancelStatus = packed struct(u32) {
143155 requested: bool,
......@@ -772,6 +784,7 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v
772784 .status = .{ .queue_next = null },
773785 .cancel_status = .unrequested,
774786 .cancel_protection = .unblocked,
787 .name = if (tracy.enable) "main task",
775788 };
776789 const main_thread = &ev.threads.allocated[0];
777790 Thread.self = main_thread;
......@@ -802,11 +815,13 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v
802815 ),
803816 .idle_search_index = 1,
804817 .steal_ready_search_index = 1,
818 .name_arena = .{},
805819 .csprng = .uninitialized,
806820 };
807821 errdefer main_thread.io_uring.deinit();
808822 log.debug("created main idle {*}", .{&main_thread.idle_context});
809823 log.debug("created main {*}", .{main_fiber});
824 if (tracy.enable) tracy.fiberEnter(main_fiber.name);
810825}
811826
812827pub fn deinit(ev: *Evented) void {
......@@ -958,6 +973,7 @@ fn schedule(ev: *Evented, thread: *Thread, ready_queue: Fiber.Queue) bool {
958973 },
959974 .idle_search_index = 0,
960975 .steal_ready_search_index = 0,
976 .name_arena = .{},
961977 .csprng = .uninitialized,
962978 };
963979 new_thread.thread = std.Thread.spawn(.{
......@@ -1160,6 +1176,12 @@ const SwitchMessage = struct {
11601176 fn handle(message: *const SwitchMessage, ev: *Evented) void {
11611177 const thread: *Thread = .current();
11621178 thread.current_context = message.contexts.ready;
1179 if (tracy.enable) {
1180 if (message.contexts.ready != &thread.idle_context) {
1181 const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.ready));
1182 tracy.fiberEnter(fiber.name);
1183 } else tracy.fiberLeave();
1184 }
11631185 switch (message.pending_task) {
11641186 .nothing => {},
11651187 .reschedule => if (message.contexts.prev != &thread.idle_context) {
......@@ -1543,6 +1565,17 @@ fn concurrent(
15431565 .status = .{ .queue_next = null },
15441566 .cancel_status = .unrequested,
15451567 .cancel_protection = .unblocked,
1568 .name = if (tracy.enable) name: {
1569 const thread: *Thread = .current();
1570 var name_arena = thread.name_arena.promote(std.heap.page_allocator);
1571 defer thread.name_arena = name_arena.state;
1572 break :name std.fmt.allocPrintSentinel(
1573 name_arena.allocator(),
1574 "task {d}",
1575 .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)},
1576 0,
1577 ) catch return error.ConcurrencyUnavailable;
1578 },
15461579 };
15471580 closure.* = .{
15481581 .ev = ev,
......@@ -1920,6 +1953,17 @@ fn groupConcurrent(
19201953 .status = .{ .queue_next = null },
19211954 .cancel_status = .unrequested,
19221955 .cancel_protection = .unblocked,
1956 .name = if (tracy.enable) name: {
1957 const thread: *Thread = .current();
1958 var name_arena = thread.name_arena.promote(std.heap.page_allocator);
1959 defer thread.name_arena = name_arena.state;
1960 break :name std.fmt.allocPrintSentinel(
1961 name_arena.allocator(),
1962 "group task {d}",
1963 .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)},
1964 0,
1965 ) catch return error.ConcurrencyUnavailable;
1966 },
19231967 };
19241968 closure.* = .{
19251969 .ev = ev,
src/main.zig+1-1
......@@ -21,7 +21,7 @@ const AstGen = std.zig.AstGen;
2121const ZonGen = std.zig.ZonGen;
2222const Server = std.zig.Server;
2323
24const tracy = @import("tracy.zig");
24pub const tracy = @import("tracy.zig");
2525const Compilation = @import("Compilation.zig");
2626const link = @import("link.zig");
2727const Package = @import("Package.zig");
src/tracy.zig+12
......@@ -98,6 +98,16 @@ pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name
9898 }
9999}
100100
101pub inline fn fiberEnter(fiber: [*:0]const u8) void {
102 if (!enable) return;
103 ___tracy_fiber_enter(fiber);
104}
105
106pub inline fn fiberLeave() void {
107 if (!enable) return;
108 ___tracy_fiber_leave();
109}
110
101111pub fn tracyAllocator(allocator: std.mem.Allocator) TracyAllocator(null) {
102112 return TracyAllocator(null).init(allocator);
103113}
......@@ -318,6 +328,8 @@ extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const anyopaque, depth
318328extern fn ___tracy_emit_logString(severity: MessageSeverity, color: i32, callstack_depth: i32, size: usize, txt: [*]const u8) void;
319329extern fn ___tracy_emit_logStringL(severity: MessageSeverity, color: i32, callstack_depth: i32, txt: [*:0]const u8) void;
320330extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void;
331extern fn ___tracy_fiber_enter(fiber: [*:0]const u8) void;
332extern fn ___tracy_fiber_leave() void;
321333
322334const ___tracy_source_location_data = extern struct {
323335 name: ?[*:0]const u8,