authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-18 19:03:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-18 21:55:37-04:00
logc9a0ec25e0baae7f128a8f7efe4d308af7fad753
tree71892b6263beda3d803b02c724733aba98cb39ef
parent355319fb674073234ea2f356a310577fb982f72b

self-hosted: add Tracy integration

This tool helps give an intuitive picture of performance. This will help us understand where to improve the code.

5 files changed, 81 insertions(+), 2 deletions(-)

build.zig+13
...@@ -72,9 +72,22 @@ pub fn build(b: *Builder) !void {...@@ -72,9 +72,22 @@ pub fn build(b: *Builder) !void {
72 if (!only_install_lib_files) {72 if (!only_install_lib_files) {
73 exe.install();73 exe.install();
74 }74 }
75 const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source");
75 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse false;76 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse false;
76 if (link_libc) exe.linkLibC();77 if (link_libc) exe.linkLibC();
7778
79 exe.addBuildOption(bool, "enable_tracy", tracy != null);
80 if (tracy) |tracy_path| {
81 const client_cpp = fs.path.join(
82 b.allocator,
83 &[_][]const u8{ tracy_path, "TracyClient.cpp" },
84 ) catch unreachable;
85 exe.addIncludeDir(tracy_path);
86 exe.addCSourceFile(client_cpp, &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" });
87 exe.linkSystemLibraryName("c++");
88 exe.linkLibC();
89 }
90
78 b.installDirectory(InstallDirectoryOptions{91 b.installDirectory(InstallDirectoryOptions{
79 .source_dir = "lib",92 .source_dir = "lib",
80 .install_dir = .Lib,93 .install_dir = .Lib,
lib/std/build.zig+3-2
...@@ -1905,10 +1905,11 @@ pub const LibExeObjStep = struct {...@@ -1905,10 +1905,11 @@ pub const LibExeObjStep = struct {
1905 builder.allocator,1905 builder.allocator,
1906 &[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", .{self.name}) },1906 &[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", .{self.name}) },
1907 );1907 );
1908 try fs.cwd().writeFile(build_options_file, self.build_options_contents.span());1908 const path_from_root = builder.pathFromRoot(build_options_file);
1909 try fs.cwd().writeFile(path_from_root, self.build_options_contents.span());
1909 try zig_args.append("--pkg-begin");1910 try zig_args.append("--pkg-begin");
1910 try zig_args.append("build_options");1911 try zig_args.append("build_options");
1911 try zig_args.append(builder.pathFromRoot(build_options_file));1912 try zig_args.append(path_from_root);
1912 try zig_args.append("--pkg-end");1913 try zig_args.append("--pkg-end");
1913 }1914 }
19141915
src-self-hosted/Module.zig+16
...@@ -16,6 +16,7 @@ const zir = @import("zir.zig");...@@ -16,6 +16,7 @@ const zir = @import("zir.zig");
16const Module = @This();16const Module = @This();
17const Inst = ir.Inst;17const Inst = ir.Inst;
18const ast = std.zig.ast;18const ast = std.zig.ast;
19const trace = @import("tracy.zig").trace;
1920
20/// General-purpose allocator.21/// General-purpose allocator.
21allocator: *Allocator,22allocator: *Allocator,
...@@ -796,6 +797,9 @@ pub fn target(self: Module) std.Target {...@@ -796,6 +797,9 @@ pub fn target(self: Module) std.Target {
796797
797/// Detect changes to source files, perform semantic analysis, and update the output files.798/// Detect changes to source files, perform semantic analysis, and update the output files.
798pub fn update(self: *Module) !void {799pub fn update(self: *Module) !void {
800 const tracy = trace(@src());
801 defer tracy.end();
802
799 self.generation += 1;803 self.generation += 1;
800804
801 // TODO Use the cache hash file system to detect which source files changed.805 // TODO Use the cache hash file system to detect which source files changed.
...@@ -1050,6 +1054,9 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {...@@ -1050,6 +1054,9 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1050}1054}
10511055
1052fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {1056fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
1057 const tracy = trace(@src());
1058 defer tracy.end();
1059
1053 const file_scope = decl.scope.cast(Scope.File).?;1060 const file_scope = decl.scope.cast(Scope.File).?;
1054 const tree = try self.getAstTree(file_scope);1061 const tree = try self.getAstTree(file_scope);
1055 const ast_node = tree.root_node.decls()[decl.src_index];1062 const ast_node = tree.root_node.decls()[decl.src_index];
...@@ -1330,6 +1337,9 @@ fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.Integer...@@ -1330,6 +1337,9 @@ fn astGenIntegerLiteral(self: *Module, scope: *Scope, int_lit: *ast.Node.Integer
1330}1337}
13311338
1332fn astGenBlock(self: *Module, scope: *Scope, block_node: *ast.Node.Block) !void {1339fn astGenBlock(self: *Module, scope: *Scope, block_node: *ast.Node.Block) !void {
1340 const tracy = trace(@src());
1341 defer tracy.end();
1342
1333 if (block_node.label) |label| {1343 if (block_node.label) |label| {
1334 return self.failTok(scope, label, "TODO implement labeled blocks", .{});1344 return self.failTok(scope, label, "TODO implement labeled blocks", .{});
1335 }1345 }
...@@ -1526,6 +1536,9 @@ fn getSrcModule(self: *Module, root_scope: *Scope.ZIRModule) !*zir.Module {...@@ -1526,6 +1536,9 @@ fn getSrcModule(self: *Module, root_scope: *Scope.ZIRModule) !*zir.Module {
1526}1536}
15271537
1528fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {1538fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
1539 const tracy = trace(@src());
1540 defer tracy.end();
1541
1529 switch (root_scope.status) {1542 switch (root_scope.status) {
1530 .never_loaded, .unloaded_success => {1543 .never_loaded, .unloaded_success => {
1531 try self.failed_files.ensureCapacity(self.failed_files.size + 1);1544 try self.failed_files.ensureCapacity(self.failed_files.size + 1);
...@@ -1739,6 +1752,9 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {...@@ -1739,6 +1752,9 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
1739}1752}
17401753
1741fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {1754fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1755 const tracy = trace(@src());
1756 defer tracy.end();
1757
1742 // Use the Decl's arena for function memory.1758 // Use the Decl's arena for function memory.
1743 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);1759 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
1744 defer decl.typed_value.most_recent.arena.?.* = arena.state;1760 defer decl.typed_value.most_recent.arena.?.* = arena.state;
src-self-hosted/codegen.zig+4
...@@ -10,6 +10,7 @@ const Module = @import("Module.zig");...@@ -10,6 +10,7 @@ const Module = @import("Module.zig");
10const ErrorMsg = Module.ErrorMsg;10const ErrorMsg = Module.ErrorMsg;
11const Target = std.Target;11const Target = std.Target;
12const Allocator = mem.Allocator;12const Allocator = mem.Allocator;
13const trace = @import("tracy.zig").trace;
1314
14pub const Result = union(enum) {15pub const Result = union(enum) {
15 /// The `code` parameter passed to `generateSymbol` has the value appended.16 /// The `code` parameter passed to `generateSymbol` has the value appended.
...@@ -29,6 +30,9 @@ pub fn generateSymbol(...@@ -29,6 +30,9 @@ pub fn generateSymbol(
29 /// A Decl that this symbol depends on had a semantic analysis failure.30 /// A Decl that this symbol depends on had a semantic analysis failure.
30 AnalysisFail,31 AnalysisFail,
31}!Result {32}!Result {
33 const tracy = trace(@src());
34 defer tracy.end();
35
32 switch (typed_value.ty.zigTypeTag()) {36 switch (typed_value.ty.zigTypeTag()) {
33 .Fn => {37 .Fn => {
34 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;38 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
src-self-hosted/tracy.zig created+45
...@@ -0,0 +1,45 @@
1pub const std = @import("std");
2
3pub const enable = @import("build_options").enable_tracy;
4
5extern fn ___tracy_emit_zone_begin_callstack(
6 srcloc: *const ___tracy_source_location_data,
7 depth: c_int,
8 active: c_int,
9) ___tracy_c_zone_context;
10
11extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void;
12
13pub const ___tracy_source_location_data = extern struct {
14 name: ?[*:0]const u8,
15 function: [*:0]const u8,
16 file: [*:0]const u8,
17 line: u32,
18 color: u32,
19};
20
21pub const ___tracy_c_zone_context = extern struct {
22 id: u32,
23 active: c_int,
24
25 pub fn end(self: ___tracy_c_zone_context) void {
26 ___tracy_emit_zone_end(self);
27 }
28};
29
30pub const Ctx = if (enable) ___tracy_c_zone_context else struct {
31 pub fn end(self: Ctx) void {}
32};
33
34pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx {
35 if (!enable) return .{};
36
37 const loc: ___tracy_source_location_data = .{
38 .name = null,
39 .function = src.fn_name.ptr,
40 .file = src.file.ptr,
41 .line = src.line,
42 .color = 0,
43 };
44 return ___tracy_emit_zone_begin_callstack(&loc, 1, 1);
45}