integrate tracy more deeply

This commit is contained in:
Mitchell Hashimoto
2022-04-29 13:39:56 -07:00
parent 10736e2eb4
commit 330d2ea270
5 changed files with 107 additions and 17 deletions

View File

@ -8,6 +8,7 @@ const Allocator = std.mem.Allocator;
const glfw = @import("glfw"); const glfw = @import("glfw");
const Window = @import("Window.zig"); const Window = @import("Window.zig");
const libuv = @import("libuv/main.zig"); const libuv = @import("libuv/main.zig");
const tracy = @import("tracy/tracy.zig");
const log = std.log.scoped(.app); const log = std.log.scoped(.app);
@ -84,7 +85,15 @@ pub fn run(self: App) !void {
}).callback); }).callback);
while (!self.window.shouldClose()) { while (!self.window.shouldClose()) {
try self.window.run(); // Mark this so we're in a totally different "frame"
tracy.frameMark();
// Track the render part of the frame separately.
{
const frame = tracy.frame("render");
defer frame.end();
try self.window.run();
}
// Block for any glfw events. This may also be an "empty" event // Block for any glfw events. This may also be an "empty" event
// posted by the libuv watcher so that we trigger a libuv loop tick. // posted by the libuv watcher so that we trigger a libuv loop tick.
@ -103,6 +112,8 @@ pub fn run(self: App) !void {
} }
// Run the libuv loop // Run the libuv loop
const frame = tracy.frame("libuv");
defer frame.end();
try embed.loopRun(); try embed.loopRun();
} }

View File

@ -10,6 +10,7 @@ const FontAtlas = @import("FontAtlas.zig");
const Terminal = @import("terminal/Terminal.zig"); const Terminal = @import("terminal/Terminal.zig");
const gl = @import("opengl.zig"); const gl = @import("opengl.zig");
const gb = @import("gb_math.zig"); const gb = @import("gb_math.zig");
const trace = @import("tracy/tracy.zig").trace;
const log = std.log.scoped(.grid); const log = std.log.scoped(.grid);
@ -343,6 +344,9 @@ pub fn setScreenSize(self: *Grid, dim: ScreenSize) !void {
} }
pub fn render(self: Grid) !void { pub fn render(self: Grid) !void {
const t = trace(@src());
defer t.end();
// If we have no cells to render, then we render nothing. // If we have no cells to render, then we render nothing.
if (self.cells.items.len == 0) return; if (self.cells.items.len == 0) return;

View File

@ -17,6 +17,7 @@ const Pty = @import("Pty.zig");
const Command = @import("Command.zig"); const Command = @import("Command.zig");
const Terminal = @import("terminal/Terminal.zig"); const Terminal = @import("terminal/Terminal.zig");
const SegmentedPool = @import("segmented_pool.zig").SegmentedPool; const SegmentedPool = @import("segmented_pool.zig").SegmentedPool;
const trace = @import("tracy/tracy.zig").trace;
const log = std.log.scoped(.window); const log = std.log.scoped(.window);
@ -231,6 +232,9 @@ pub fn shouldClose(self: Window) bool {
} }
pub fn run(self: Window) !void { pub fn run(self: Window) !void {
const tracy = trace(@src());
defer tracy.end();
// Set our background // Set our background
gl.clearColor(0.2, 0.3, 0.3, 1.0); gl.clearColor(0.2, 0.3, 0.3, 1.0);
gl.clear(gl.c.GL_COLOR_BUFFER_BIT); gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
@ -243,6 +247,9 @@ pub fn run(self: Window) !void {
} }
fn sizeCallback(window: glfw.Window, width: i32, height: i32) void { fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
const tracy = trace(@src());
defer tracy.end();
// glfw gives us signed integers, but negative width/height is n // glfw gives us signed integers, but negative width/height is n
// non-sensical so we use unsigned throughout, so assert. // non-sensical so we use unsigned throughout, so assert.
assert(width >= 0); assert(width >= 0);
@ -279,6 +286,9 @@ fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
} }
fn charCallback(window: glfw.Window, codepoint: u21) void { fn charCallback(window: glfw.Window, codepoint: u21) void {
const tracy = trace(@src());
defer tracy.end();
const win = window.getUserPointer(Window) orelse return; const win = window.getUserPointer(Window) orelse return;
// Write the character to the pty // Write the character to the pty
@ -299,6 +309,9 @@ fn keyCallback(
action: glfw.Action, action: glfw.Action,
mods: glfw.Mods, mods: glfw.Mods,
) void { ) void {
const tracy = trace(@src());
defer tracy.end();
_ = scancode; _ = scancode;
_ = mods; _ = mods;
@ -352,6 +365,9 @@ fn keyCallback(
} }
fn focusCallback(window: glfw.Window, focused: bool) void { fn focusCallback(window: glfw.Window, focused: bool) void {
const tracy = trace(@src());
defer tracy.end();
const win = window.getUserPointer(Window) orelse return; const win = window.getUserPointer(Window) orelse return;
if (focused) { if (focused) {
win.wakeup = true; win.wakeup = true;
@ -367,17 +383,27 @@ fn focusCallback(window: glfw.Window, focused: bool) void {
} }
fn cursorTimerCallback(t: *libuv.Timer) void { fn cursorTimerCallback(t: *libuv.Timer) void {
const tracy = trace(@src());
defer tracy.end();
const win = t.getData(Window) orelse return; const win = t.getData(Window) orelse return;
win.grid.cursor_visible = !win.grid.cursor_visible; win.grid.cursor_visible = !win.grid.cursor_visible;
win.grid.updateCells(win.terminal) catch unreachable; win.grid.updateCells(win.terminal) catch unreachable;
} }
fn ttyReadAlloc(t: *libuv.Tty, size: usize) ?[]u8 { fn ttyReadAlloc(t: *libuv.Tty, size: usize) ?[]u8 {
const tracy = trace(@src());
defer tracy.end();
const alloc = t.loop().getData(Allocator).?.*; const alloc = t.loop().getData(Allocator).?.*;
return alloc.alloc(u8, size) catch null; return alloc.alloc(u8, size) catch null;
} }
fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void { fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
const tracy = trace(@src());
tracy.color(0xEAEA7F); // yellow-ish
defer tracy.end();
const win = t.getData(Window).?; const win = t.getData(Window).?;
defer win.alloc.free(buf); defer win.alloc.free(buf);
@ -411,6 +437,9 @@ fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
} }
fn ttyWrite(req: *libuv.WriteReq, status: i32) void { fn ttyWrite(req: *libuv.WriteReq, status: i32) void {
const tracy = trace(@src());
defer tracy.end();
const tty = req.handle(libuv.Tty).?; const tty = req.handle(libuv.Tty).?;
const win = tty.getData(Window).?; const win = tty.getData(Window).?;
win.write_req_pool.put(); win.write_req_pool.put();

View File

@ -6,9 +6,6 @@ const App = @import("App.zig");
const trace = @import("tracy/tracy.zig").trace; const trace = @import("tracy/tracy.zig").trace;
pub fn main() !void { pub fn main() !void {
const tracy = trace(@src());
defer tracy.end();
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
const gpa = general_purpose_allocator.allocator(); const gpa = general_purpose_allocator.allocator();
defer _ = general_purpose_allocator.deinit(); defer _ = general_purpose_allocator.deinit();

View File

@ -22,28 +22,52 @@ const Impl = struct {
const has_callstack_support = @hasDecl(c, "TRACY_HAS_CALLSTACK") and @hasDecl(c, "TRACY_CALLSTACK"); const has_callstack_support = @hasDecl(c, "TRACY_HAS_CALLSTACK") and @hasDecl(c, "TRACY_CALLSTACK");
const callstack_enabled: c_int = if (has_callstack_support) c.TRACY_CALLSTACK else 0; const callstack_enabled: c_int = if (has_callstack_support) c.TRACY_CALLSTACK else 0;
pub const ZoneCtx = struct { /// A zone represents the lifetime of a special on-stack profiler variable.
/// Typically it would exist for the duration of a whole scope of the
/// profiled function, but you also can measure time spent in scopes of a
/// for-loop or an if-branch.
pub const Zone = struct {
zone: c.___tracy_c_zone_context, zone: c.___tracy_c_zone_context,
pub inline fn text(self: ZoneCtx, val: []const u8) void { /// Text description of a zone.
pub inline fn text(self: Zone, val: []const u8) void {
c.___tracy_emit_zone_text(self.zone, val.ptr, val.len); c.___tracy_emit_zone_text(self.zone, val.ptr, val.len);
} }
pub inline fn name(self: ZoneCtx, val: []const u8) void { /// Name of the zone.
pub inline fn name(self: Zone, val: []const u8) void {
c.___tracy_emit_zone_name(self.zone, val.ptr, val.len); c.___tracy_emit_zone_name(self.zone, val.ptr, val.len);
} }
pub inline fn value(self: ZoneCtx, val: u64) void { /// Color of the zone in the UI. Specify the value as RGB
/// using hex: 0xRRGGBB.
pub inline fn color(self: Zone, val: u32) void {
c.___tracy_emit_zone_color(self.zone, val);
}
/// A value associated with the zone.
pub inline fn value(self: Zone, val: u64) void {
c.___tracy_emit_zone_value(self.zone, val); c.___tracy_emit_zone_value(self.zone, val);
} }
pub inline fn end(self: ZoneCtx) void { /// End the zone.
pub inline fn end(self: Zone) void {
c.___tracy_emit_zone_end(self.zone); c.___tracy_emit_zone_end(self.zone);
} }
}; };
/// Tracy profiles within the context of a frame. This represents
/// a single frame.
pub fn Frame(comptime name: [:0]const u8) type {
return struct {
pub fn end(_: @This()) void {
c.___tracy_emit_frame_mark_end(name.ptr);
}
};
}
/// Start a trace. Defer calling end() to end the trace. /// Start a trace. Defer calling end() to end the trace.
pub inline fn trace(comptime src: SourceLocation) ZoneCtx { pub inline fn trace(comptime src: SourceLocation) Zone {
const callstack_depth = 10; // TODO configurable const callstack_depth = 10; // TODO configurable
const static = struct { const static = struct {
@ -62,20 +86,45 @@ const Impl = struct {
else else
c.___tracy_emit_zone_begin(&static.loc, 1); c.___tracy_emit_zone_begin(&static.loc, 1);
return ZoneCtx{ .zone = zone }; return Zone{ .zone = zone };
}
/// Mark the boundary of a frame. Good for continuous frames. For
/// discontinous frames, use frame() and defer end().
pub inline fn frameMark() void {
c.___tracy_emit_frame_mark(null);
}
/// Start a discontinuous frame.
pub inline fn frame(comptime name: [:0]const u8) Frame(name) {
c.___tracy_emit_frame_mark_start(name.ptr);
return .{};
} }
}; };
const Noop = struct { const Noop = struct {
pub const ZoneCtx = struct { pub const Zone = struct {
pub inline fn text(_: ZoneCtx, _: []const u8) void {} pub inline fn text(_: Zone, _: []const u8) void {}
pub inline fn name(_: ZoneCtx, _: []const u8) void {} pub inline fn name(_: Zone, _: []const u8) void {}
pub inline fn value(_: ZoneCtx, _: u64) void {} pub inline fn color(_: Zone, _: u32) void {}
pub inline fn end(_: ZoneCtx) void {} pub inline fn value(_: Zone, _: u64) void {}
pub inline fn end(_: Zone) void {}
}; };
pub inline fn trace(comptime src: SourceLocation) ZoneCtx { pub fn Frame(comptime _: [:0]const u8) type {
return struct {
pub fn end(_: @This()) void {}
};
}
pub inline fn trace(comptime src: SourceLocation) Zone {
_ = src; _ = src;
return .{}; return .{};
} }
pub inline fn frameMark() void {}
pub inline fn frame(comptime name: [*:0]const u8) Frame(name) {
return .{};
}
}; };