mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
Fixes ENG-21287
Build times, from `bun run build && echo '//' >> src/main.zig && time
bun run build`
|Platform|0.14.1|0.15.2|Speedup|
|-|-|-|-|
|macos debug asan|126.90s|106.27s|1.19x|
|macos debug noasan|60.62s|50.85s|1.19x|
|linux debug asan|292.77s|241.45s|1.21x|
|linux debug noasan|146.58s|130.94s|1.12x|
|linux debug use_llvm=false|n/a|78.27s|1.87x|
|windows debug asan|177.13s|142.55s|1.24x|
Runtime performance:
- next build memory usage may have gone up by 5%. Otherwise seems the
same. Some code with writers may have gotten slower, especially one
instance of a counting writer and a few instances of unbuffered writers
that now have vtable overhead.
- File size reduced by 800kb (from 100.2mb to 99.4mb)
Improvements:
- `@export` hack is no longer needed for watch
- native x86_64 backend for linux builds faster. to use it, set use_llvm
false and no_link_obj false. also set `ASAN_OPTIONS=detect_leaks=0`
otherwise it will spam the output with tens of thousands of lines of
debug info errors. may need to use the zig lldb fork for debugging.
- zig test-obj, which we will be able to use for zig unit tests
Still an issue:
- false 'dependency loop' errors remain in watch mode
- watch mode crashes observed
Follow-up:
- [ ] search `comptime Writer: type` and `comptime W: type` and remove
- [ ] remove format_mode in our zig fork
- [ ] remove deprecated.zig autoFormatLabelFallback
- [ ] remove deprecated.zig autoFormatLabel
- [ ] remove deprecated.BufferedWriter and BufferedReader
- [ ] remove override_no_export_cpp_apis as it is no longer needed
- [ ] css Parser(W) -> Parser, and remove all the comptime writer: type
params
- [ ] remove deprecated writer fully
Files that add lines:
```
649 src/deprecated.zig
167 scripts/pack-codegen-for-zig-team.ts
54 scripts/cleartrace-impl.js
46 scripts/cleartrace.ts
43 src/windows.zig
18 src/fs.zig
17 src/bun.js/ConsoleObject.zig
16 src/output.zig
12 src/bun.js/test/debug.zig
12 src/bun.js/node/node_fs.zig
8 src/env_loader.zig
7 src/css/printer.zig
7 src/cli/init_command.zig
7 src/bun.js/node.zig
6 src/string/escapeRegExp.zig
6 src/install/PnpmMatcher.zig
5 src/bun.js/webcore/Blob.zig
4 src/crash_handler.zig
4 src/bun.zig
3 src/install/lockfile/bun.lock.zig
3 src/cli/update_interactive_command.zig
3 src/cli/pack_command.zig
3 build.zig
2 src/Progress.zig
2 src/install/lockfile/lockfile_json_stringify_for_debugging.zig
2 src/css/small_list.zig
2 src/bun.js/webcore/prompt.zig
1 test/internal/ban-words.test.ts
1 test/internal/ban-limits.json
1 src/watcher/WatcherTrace.zig
1 src/transpiler.zig
1 src/shell/builtin/cp.zig
1 src/js_printer.zig
1 src/io/PipeReader.zig
1 src/install/bin.zig
1 src/css/selectors/selector.zig
1 src/cli/run_command.zig
1 src/bun.js/RuntimeTranspilerStore.zig
1 src/bun.js/bindings/JSRef.zig
1 src/bake/DevServer.zig
```
Files that remove lines:
```
-1 src/test/recover.zig
-1 src/sql/postgres/SocketMonitor.zig
-1 src/sql/mysql/MySQLRequestQueue.zig
-1 src/sourcemap/CodeCoverage.zig
-1 src/css/values/color_js.zig
-1 src/compile_target.zig
-1 src/bundler/linker_context/convertStmtsForChunk.zig
-1 src/bundler/bundle_v2.zig
-1 src/bun.js/webcore/blob/read_file.zig
-1 src/ast/base.zig
-2 src/sql/postgres/protocol/ArrayList.zig
-2 src/shell/builtin/mkdir.zig
-2 src/install/PackageManager/patchPackage.zig
-2 src/install/PackageManager/PackageManagerDirectories.zig
-2 src/fmt.zig
-2 src/css/declaration.zig
-2 src/css/css_parser.zig
-2 src/collections/baby_list.zig
-2 src/bun.js/bindings/ZigStackFrame.zig
-2 src/ast/E.zig
-3 src/StandaloneModuleGraph.zig
-3 src/deps/picohttp.zig
-3 src/deps/libuv.zig
-3 src/btjs.zig
-4 src/threading/Futex.zig
-4 src/shell/builtin/touch.zig
-4 src/meta.zig
-4 src/install/lockfile.zig
-4 src/css/selectors/parser.zig
-5 src/shell/interpreter.zig
-5 src/css/error.zig
-5 src/bun.js/web_worker.zig
-5 src/bun.js.zig
-6 src/cli/test_command.zig
-6 src/bun.js/VirtualMachine.zig
-6 src/bun.js/uuid.zig
-6 src/bun.js/bindings/JSValue.zig
-9 src/bun.js/test/pretty_format.zig
-9 src/bun.js/api/BunObject.zig
-14 src/install/install_binding.zig
-14 src/fd.zig
-14 src/bun.js/node/path.zig
-14 scripts/pack-codegen-for-zig-team.sh
-17 src/bun.js/test/diff_format.zig
```
`git diff --numstat origin/main...HEAD | awk '{ print ($1-$2)"\t"$3 }' |
sort -rn`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Meghan Denny <meghan@bun.com>
Co-authored-by: tayor.fish <contact@taylor.fish>
559 lines
20 KiB
Zig
559 lines
20 KiB
Zig
/// https://github.com/wolfpld/tracy
|
|
/// To use this module, you must have Tracy installed on your system.
|
|
/// On macOS, you can install it with `brew install tracy`.
|
|
///
|
|
/// This file is based on the code from Zig's transpiler source.
|
|
/// Thank you to the Zig team
|
|
///
|
|
const std = @import("std");
|
|
|
|
pub const enable_allocation = false;
|
|
pub const enable_callstack = false;
|
|
pub var enable = false;
|
|
|
|
const ___tracy_c_zone_context = extern struct {
|
|
id: u32 = 0,
|
|
active: c_int = 0,
|
|
|
|
pub inline fn end(self: @This()) void {
|
|
if (!enable) return;
|
|
___tracy_emit_zone_end(self);
|
|
}
|
|
|
|
pub inline fn addText(self: @This(), text: []const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_zone_text(self, text.ptr, text.len);
|
|
}
|
|
|
|
pub inline fn setName(self: @This(), name: []const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_zone_name(self, name.ptr, name.len);
|
|
}
|
|
|
|
pub inline fn setColor(self: @This(), color: u32) void {
|
|
if (!enable) return;
|
|
___tracy_emit_zone_color(self, color);
|
|
}
|
|
|
|
pub inline fn setValue(self: @This(), value: u64) void {
|
|
if (!enable) return;
|
|
___tracy_emit_zone_value(self, value);
|
|
}
|
|
};
|
|
|
|
pub const Ctx = ___tracy_c_zone_context;
|
|
|
|
pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx {
|
|
if (!enable) return .{};
|
|
|
|
if (enable_callstack) {
|
|
return ___tracy_emit_zone_begin_callstack(&.{
|
|
.name = null,
|
|
.function = src.fn_name.ptr,
|
|
.file = src.file.ptr,
|
|
.line = src.line,
|
|
.color = 0,
|
|
}, callstack_depth, 1);
|
|
} else {
|
|
const holder = struct {
|
|
pub const srcloc = ___tracy_source_location_data{
|
|
.name = null,
|
|
.function = src.fn_name.ptr,
|
|
.file = src.file.ptr,
|
|
.line = src.line,
|
|
.color = 0,
|
|
};
|
|
};
|
|
|
|
return ___tracy_emit_zone_begin(&holder.srcloc, 1);
|
|
}
|
|
}
|
|
|
|
pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name: [*:0]const u8) Ctx {
|
|
if (!enable) return .{};
|
|
|
|
if (enable_callstack) {
|
|
return ___tracy_emit_zone_begin_callstack(&.{
|
|
.name = name,
|
|
.function = src.fn_name.ptr,
|
|
.file = src.file.ptr,
|
|
.line = src.line,
|
|
.color = 0,
|
|
}, callstack_depth, 1);
|
|
} else {
|
|
const holder = struct {
|
|
pub var data: ___tracy_source_location_data = undefined;
|
|
};
|
|
holder.data = ___tracy_source_location_data{
|
|
.name = name,
|
|
.function = src.fn_name.ptr,
|
|
.file = src.file.ptr,
|
|
.line = src.line,
|
|
.color = 0,
|
|
};
|
|
return ___tracy_emit_zone_begin(&holder.data, 1);
|
|
}
|
|
}
|
|
|
|
pub fn tracyAllocator(allocator: std.mem.Allocator) TracyAllocator(null) {
|
|
return TracyAllocator(null).init(allocator);
|
|
}
|
|
|
|
pub fn TracyAllocator(comptime name: ?[:0]const u8) type {
|
|
return struct {
|
|
parent_allocator: std.mem.Allocator,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn init(parent_allocator: std.mem.Allocator) Self {
|
|
return .{
|
|
.parent_allocator = parent_allocator,
|
|
};
|
|
}
|
|
|
|
pub fn allocator(self: *Self) std.mem.Allocator {
|
|
return .{
|
|
.ptr = self,
|
|
.vtable = &.{
|
|
.alloc = allocFn,
|
|
.resize = resizeFn,
|
|
.free = freeFn,
|
|
},
|
|
};
|
|
}
|
|
|
|
fn allocFn(ptr: *anyopaque, len: usize, ptr_align: u8, ret_addr: usize) ?[*]u8 {
|
|
const self = @as(*Self, @ptrCast(@alignCast(ptr)));
|
|
const result = self.parent_allocator.rawAlloc(len, ptr_align, ret_addr);
|
|
if (result) |data| {
|
|
if (len != 0) {
|
|
if (name) |n| {
|
|
allocNamed(data, len, n);
|
|
} else {
|
|
alloc(data, len);
|
|
}
|
|
}
|
|
} else {
|
|
messageColor("allocation failed", 0xFF0000);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
fn resizeFn(ptr: *anyopaque, buf: []u8, buf_align: u8, new_len: usize, ret_addr: usize) bool {
|
|
const self = @as(*Self, @ptrCast(@alignCast(ptr)));
|
|
if (self.parent_allocator.rawResize(buf, buf_align, new_len, ret_addr)) {
|
|
if (name) |n| {
|
|
freeNamed(buf.ptr, n);
|
|
allocNamed(buf.ptr, new_len, n);
|
|
} else {
|
|
free(buf.ptr);
|
|
alloc(buf.ptr, new_len);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// during normal operation the compiler hits this case thousands of times due to this
|
|
// emitting messages for it is both slow and causes clutter
|
|
return false;
|
|
}
|
|
|
|
fn freeFn(ptr: *anyopaque, buf: []u8, buf_align: u8, ret_addr: usize) void {
|
|
const self = @as(*Self, @ptrCast(@alignCast(ptr)));
|
|
self.parent_allocator.rawFree(buf, buf_align, ret_addr);
|
|
// this condition is to handle free being called on an empty slice that was never even allocated
|
|
// example case: `std.process.getSelfExeSharedLibPaths` can return `&[_][:0]u8{}`
|
|
if (buf.len != 0) {
|
|
if (name) |n| {
|
|
freeNamed(buf.ptr, n);
|
|
} else {
|
|
free(buf.ptr);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// This function only accepts comptime-known strings, see `messageCopy` for runtime strings
|
|
pub inline fn message(comptime msg: [:0]const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_messageL(msg.ptr, if (enable_callstack) callstack_depth else 0);
|
|
}
|
|
|
|
// This function only accepts comptime-known strings, see `messageColorCopy` for runtime strings
|
|
pub inline fn messageColor(comptime msg: [:0]const u8, color: u32) void {
|
|
if (!enable) return;
|
|
___tracy_emit_messageLC(msg.ptr, color, if (enable_callstack) callstack_depth else 0);
|
|
}
|
|
|
|
pub inline fn messageCopy(msg: []const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_message(msg.ptr, msg.len, if (enable_callstack) callstack_depth else 0);
|
|
}
|
|
|
|
pub inline fn messageColorCopy(msg: [:0]const u8, color: u32) void {
|
|
if (!enable) return;
|
|
___tracy_emit_messageC(msg.ptr, msg.len, color, if (enable_callstack) callstack_depth else 0);
|
|
}
|
|
|
|
pub inline fn frameMark() void {
|
|
if (!enable) return;
|
|
___tracy_emit_frame_mark(null);
|
|
}
|
|
|
|
pub inline fn frameMarkNamed(comptime name: [:0]const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_frame_mark(name.ptr);
|
|
}
|
|
|
|
pub inline fn namedFrame(comptime name: [:0]const u8) Frame(name) {
|
|
frameMarkStart(name);
|
|
return .{};
|
|
}
|
|
|
|
pub fn Frame(comptime name: [:0]const u8) type {
|
|
return struct {
|
|
pub fn end(_: @This()) void {
|
|
frameMarkEnd(name);
|
|
}
|
|
};
|
|
}
|
|
|
|
inline fn frameMarkStart(comptime name: [:0]const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_frame_mark_start(name.ptr);
|
|
}
|
|
|
|
inline fn frameMarkEnd(comptime name: [:0]const u8) void {
|
|
if (!enable) return;
|
|
___tracy_emit_frame_mark_end(name.ptr);
|
|
}
|
|
|
|
inline fn alloc(ptr: [*]u8, len: usize) void {
|
|
if (!enable) return;
|
|
|
|
if (enable_callstack) {
|
|
___tracy_emit_memory_alloc_callstack(ptr, len, callstack_depth, 0);
|
|
} else {
|
|
___tracy_emit_memory_alloc(ptr, len, 0);
|
|
}
|
|
}
|
|
|
|
inline fn allocNamed(ptr: [*]u8, len: usize, comptime name: [:0]const u8) void {
|
|
if (!enable) return;
|
|
|
|
if (enable_callstack) {
|
|
___tracy_emit_memory_alloc_callstack_named(ptr, len, callstack_depth, 0, name.ptr);
|
|
} else {
|
|
___tracy_emit_memory_alloc_named(ptr, len, 0, name.ptr);
|
|
}
|
|
}
|
|
|
|
inline fn free(ptr: [*]u8) void {
|
|
if (!enable) return;
|
|
|
|
if (enable_callstack) {
|
|
___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0);
|
|
} else {
|
|
___tracy_emit_memory_free(ptr, 0);
|
|
}
|
|
}
|
|
|
|
inline fn freeNamed(ptr: [*]u8, comptime name: [:0]const u8) void {
|
|
if (!enable) return;
|
|
|
|
if (enable_callstack) {
|
|
___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name.ptr);
|
|
} else {
|
|
___tracy_emit_memory_free_named(ptr, 0, name.ptr);
|
|
}
|
|
}
|
|
|
|
const Tracy = struct {
|
|
pub const emit_frame_mark_start = *const fn (name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_frame_mark_end = *const fn (name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_zone_begin = *const fn (
|
|
srcloc: *const ___tracy_source_location_data,
|
|
active: c_int,
|
|
) callconv(.c) ___tracy_c_zone_context;
|
|
pub const emit_zone_begin_callstack = *const fn (
|
|
srcloc: *const ___tracy_source_location_data,
|
|
depth: c_int,
|
|
active: c_int,
|
|
) callconv(.c) ___tracy_c_zone_context;
|
|
pub const emit_zone_text = *const fn (ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) callconv(.c) void;
|
|
pub const emit_zone_name = *const fn (ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) callconv(.c) void;
|
|
pub const emit_zone_color = *const fn (ctx: ___tracy_c_zone_context, color: u32) callconv(.c) void;
|
|
pub const emit_zone_value = *const fn (ctx: ___tracy_c_zone_context, value: u64) callconv(.c) void;
|
|
pub const emit_zone_end = *const fn (ctx: ___tracy_c_zone_context) callconv(.c) void;
|
|
pub const emit_memory_alloc = *const fn (ptr: *const anyopaque, size: usize, secure: c_int) callconv(.c) void;
|
|
pub const emit_memory_alloc_callstack = *const fn (ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int) callconv(.c) void;
|
|
pub const emit_memory_free = *const fn (ptr: *const anyopaque, secure: c_int) callconv(.c) void;
|
|
pub const emit_memory_free_callstack = *const fn (ptr: *const anyopaque, depth: c_int, secure: c_int) callconv(.c) void;
|
|
pub const emit_memory_alloc_named = *const fn (ptr: *const anyopaque, size: usize, secure: c_int, name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_memory_alloc_callstack_named = *const fn (ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int, name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_memory_free_named = *const fn (ptr: *const anyopaque, secure: c_int, name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_memory_free_callstack_named = *const fn (ptr: *const anyopaque, depth: c_int, secure: c_int, name: [*:0]const u8) callconv(.c) void;
|
|
pub const emit_message = *const fn (txt: [*]const u8, size: usize, callstack: c_int) callconv(.c) void;
|
|
pub const emit_messageL = *const fn (txt: [*:0]const u8, callstack: c_int) callconv(.c) void;
|
|
pub const emit_messageC = *const fn (txt: [*]const u8, size: usize, color: u32, callstack: c_int) callconv(.c) void;
|
|
pub const emit_messageLC = *const fn (txt: [*:0]const u8, color: u32, callstack: c_int) callconv(.c) void;
|
|
pub const emit_frame_mark = *const fn (name: ?[*:0]const u8) callconv(.c) void;
|
|
pub const connected = *const fn () callconv(.c) c_int;
|
|
pub const set_thread_name = *const fn (name: [*:0]const u8) callconv(.c) void;
|
|
pub const startup_profiler = *const fn () callconv(.c) void;
|
|
pub const shutdown_profiler = *const fn () callconv(.c) void;
|
|
};
|
|
|
|
fn ___tracy_startup_profiler() void {
|
|
// these might not exist
|
|
const Fn = dlsym(Tracy.startup_profiler, "___tracy_startup_profiler") orelse return;
|
|
Fn();
|
|
}
|
|
|
|
fn ___tracy_shutdown_profiler() void {
|
|
// these might not exist
|
|
const Fn = dlsym(Tracy.shutdown_profiler, "___tracy_shutdown_profiler") orelse return;
|
|
Fn();
|
|
}
|
|
|
|
pub var has_started = false;
|
|
pub fn start() void {
|
|
if (!enable or has_started) return;
|
|
___tracy_startup_profiler();
|
|
}
|
|
|
|
pub fn stop() void {
|
|
if (!enable or !has_started) return;
|
|
___tracy_shutdown_profiler();
|
|
}
|
|
|
|
fn ___tracy_connected() c_int {
|
|
const Fn = dlsym(Tracy.connected, "___tracy_connected").?;
|
|
return Fn();
|
|
}
|
|
|
|
fn ___tracy_set_thread_name(name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.set_thread_name, "___tracy_set_thread_name").?;
|
|
Fn(name);
|
|
}
|
|
|
|
fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_frame_mark_start, "___tracy_emit_frame_mark_start").?;
|
|
Fn(name);
|
|
}
|
|
fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_frame_mark_end, "___tracy_emit_frame_mark_end").?;
|
|
Fn(name);
|
|
}
|
|
fn ___tracy_emit_zone_begin(
|
|
srcloc: *const ___tracy_source_location_data,
|
|
active: c_int,
|
|
) ___tracy_c_zone_context {
|
|
const Fn = dlsym(Tracy.emit_zone_begin, "___tracy_emit_zone_begin").?;
|
|
return Fn(srcloc, active);
|
|
}
|
|
fn ___tracy_emit_zone_begin_callstack(
|
|
srcloc: *const ___tracy_source_location_data,
|
|
depth: c_int,
|
|
active: c_int,
|
|
) ___tracy_c_zone_context {
|
|
const Fn = dlsym(Tracy.emit_zone_begin_callstack, "___tracy_emit_zone_begin_callstack").?;
|
|
return Fn(srcloc, depth, active);
|
|
}
|
|
fn ___tracy_emit_zone_text(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void {
|
|
const Fn = dlsym(Tracy.emit_zone_text, "___tracy_emit_zone_text").?;
|
|
Fn(ctx, txt, size);
|
|
}
|
|
fn ___tracy_emit_zone_name(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void {
|
|
const Fn = dlsym(Tracy.emit_zone_name, "___tracy_emit_zone_name").?;
|
|
Fn(ctx, txt, size);
|
|
}
|
|
fn ___tracy_emit_zone_color(ctx: ___tracy_c_zone_context, color: u32) void {
|
|
const Fn = dlsym(Tracy.emit_zone_color, "___tracy_emit_zone_color").?;
|
|
Fn(ctx, color);
|
|
}
|
|
fn ___tracy_emit_zone_value(ctx: ___tracy_c_zone_context, value: u64) void {
|
|
const Fn = dlsym(Tracy.emit_zone_value, "___tracy_emit_zone_value").?;
|
|
Fn(ctx, value);
|
|
}
|
|
fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void {
|
|
const Fn = dlsym(Tracy.emit_zone_end, "___tracy_emit_zone_end").?;
|
|
Fn(ctx);
|
|
}
|
|
fn ___tracy_emit_memory_alloc(ptr: *const anyopaque, size: usize, secure: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_memory_alloc, "___tracy_emit_memory_alloc").?;
|
|
Fn(ptr, size, secure);
|
|
}
|
|
fn ___tracy_emit_memory_alloc_callstack(ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_memory_alloc_callstack, "___tracy_emit_memory_alloc_callstack").?;
|
|
Fn(ptr, size, depth, secure);
|
|
}
|
|
fn ___tracy_emit_memory_free(ptr: *const anyopaque, secure: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_memory_free, "___tracy_emit_memory_free").?;
|
|
Fn(ptr, secure);
|
|
}
|
|
fn ___tracy_emit_memory_free_callstack(ptr: *const anyopaque, depth: c_int, secure: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_memory_free_callstack, "___tracy_emit_memory_free_callstack").?;
|
|
Fn(ptr, depth, secure);
|
|
}
|
|
fn ___tracy_emit_memory_alloc_named(ptr: *const anyopaque, size: usize, secure: c_int, name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_memory_alloc_named, "___tracy_emit_memory_alloc_named").?;
|
|
Fn(ptr, size, secure, name);
|
|
}
|
|
fn ___tracy_emit_memory_alloc_callstack_named(ptr: *const anyopaque, size: usize, depth: c_int, secure: c_int, name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_memory_alloc_callstack_named, "___tracy_emit_memory_alloc_callstack_named").?;
|
|
Fn(ptr, size, depth, secure, name);
|
|
}
|
|
fn ___tracy_emit_memory_free_named(ptr: *const anyopaque, secure: c_int, name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_memory_free_named, "___tracy_emit_memory_free_named").?;
|
|
Fn(ptr, secure, name);
|
|
}
|
|
fn ___tracy_emit_memory_free_callstack_named(ptr: *const anyopaque, depth: c_int, secure: c_int, name: [*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_memory_free_callstack_named, "___tracy_emit_memory_free_callstack_named").?;
|
|
Fn(ptr, depth, secure, name);
|
|
}
|
|
fn ___tracy_emit_message(txt: [*]const u8, size: usize, callstack: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_message, "___tracy_emit_message").?;
|
|
Fn(txt, size, callstack);
|
|
}
|
|
fn ___tracy_emit_messageL(txt: [*:0]const u8, callstack: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_messageL, "___tracy_emit_messageL").?;
|
|
Fn(txt, callstack);
|
|
}
|
|
fn ___tracy_emit_messageC(txt: [*]const u8, size: usize, color: u32, callstack: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_messageC, "___tracy_emit_messageC").?;
|
|
Fn(txt, size, color, callstack);
|
|
}
|
|
fn ___tracy_emit_messageLC(txt: [*:0]const u8, color: u32, callstack: c_int) void {
|
|
const Fn = dlsym(Tracy.emit_messageLC, "___tracy_emit_messageLC").?;
|
|
Fn(txt, color, callstack);
|
|
}
|
|
fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void {
|
|
const Fn = dlsym(Tracy.emit_frame_mark, "___tracy_emit_frame_mark").?;
|
|
Fn(name);
|
|
}
|
|
|
|
pub fn init() bool {
|
|
if (comptime !bun.Environment.isNative) {
|
|
return false;
|
|
}
|
|
|
|
if (enable)
|
|
return true;
|
|
|
|
if (dlsym(Tracy.emit_message, "___tracy_emit_message") == null) {
|
|
return false;
|
|
}
|
|
enable = true;
|
|
return true;
|
|
}
|
|
|
|
pub fn isConnected() bool {
|
|
if (comptime !bun.Environment.isNative) {
|
|
return false;
|
|
}
|
|
|
|
if (!enable)
|
|
return false;
|
|
|
|
const Fn = dlsym(Tracy.connected, "___tracy_connected").?;
|
|
return Fn() != 0;
|
|
}
|
|
|
|
pub fn initThread(comptime name: [:0]const u8) void {
|
|
if (comptime !bun.Environment.isNative) {
|
|
return;
|
|
}
|
|
|
|
if (!enable)
|
|
return;
|
|
|
|
dlsym(Tracy.set_thread_name, "___tracy_set_thread_name").?(name.ptr);
|
|
}
|
|
|
|
const ___tracy_source_location_data = extern struct {
|
|
name: ?[*:0]const u8 = null,
|
|
function: [*:0]const u8 = "",
|
|
file: [*:0]const u8 = "",
|
|
line: u32 = 0,
|
|
color: u32 = 0,
|
|
};
|
|
|
|
fn dlsym(comptime Type: type, comptime symbol: [:0]const u8) ?Type {
|
|
if (comptime !bun.Environment.isNative) {
|
|
return null;
|
|
}
|
|
|
|
if (comptime bun.Environment.isLinux) {
|
|
// use LD_PRELOAD on linux
|
|
if (bun.C.dlsym(Type, symbol)) |val| {
|
|
return val;
|
|
}
|
|
}
|
|
|
|
const Handle = struct {
|
|
pub var handle: ?*anyopaque = null;
|
|
pub fn getter() ?*anyopaque {
|
|
return handle;
|
|
}
|
|
};
|
|
|
|
get: {
|
|
if (Handle.handle == null) {
|
|
const paths_to_try = if (bun.Environment.isMac) .{
|
|
"/usr/local/opt/tracy/lib/libtracy.dylib",
|
|
"/usr/local/lib/libtracy.dylib",
|
|
"/opt/homebrew/lib/libtracy.so",
|
|
"/opt/homebrew/lib/libtracy.dylib",
|
|
"/usr/lib/libtracy.dylib",
|
|
"libtracy.dylib",
|
|
"libtracy.so",
|
|
"libTracyClient.dylib",
|
|
"libTracyClient.so",
|
|
} else if (bun.Environment.isLinux) .{
|
|
"/usr/local/lib/libtracy.so",
|
|
"/usr/local/opt/tracy/lib/libtracy.so",
|
|
"/opt/tracy/lib/libtracy.so",
|
|
"/usr/lib/libtracy.so",
|
|
"/usr/local/lib/libTracyClient.so",
|
|
"/usr/local/opt/tracy/lib/libTracyClient.so",
|
|
"/opt/tracy/lib/libTracyClient.so",
|
|
"/usr/lib/libTracyClient.so",
|
|
"libtracy.so",
|
|
"libTracyClient.so",
|
|
} else if (bun.Environment.isWindows) .{
|
|
"tracy.dll",
|
|
} else .{};
|
|
|
|
const RLTD: std.c.RTLD = if (bun.Environment.isMac) @bitCast(@as(i32, -2)) else if (bun.Environment.isLinux) .{} else {};
|
|
|
|
if (bun.env_var.BUN_TRACY_PATH.get()) |path| {
|
|
const handle = bun.sys.dlopen(&(std.posix.toPosixPath(path) catch unreachable), RLTD);
|
|
if (handle != null) {
|
|
Handle.handle = handle;
|
|
break :get;
|
|
}
|
|
}
|
|
inline for (comptime paths_to_try) |path| {
|
|
const handle = bun.sys.dlopen(path, RLTD);
|
|
if (handle != null) {
|
|
Handle.handle = handle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Handle.handle == null)
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return bun.C.dlsymWithHandle(Type, symbol, Handle.getter);
|
|
}
|
|
|
|
const builtin = @import("builtin");
|
|
const bun = @import("bun");
|
|
|
|
const build_options = @import("build_options");
|
|
const callstack_depth = build_options.tracy_callstack_depth;
|