use arena allocator for cli commands
This commit is contained in:
parent
614f846a41
commit
a44ad0b7d0
1 changed files with 30 additions and 8 deletions
38
src/main.zig
38
src/main.zig
|
|
@ -145,12 +145,15 @@ fn resolveUserPath(
|
|||
}
|
||||
|
||||
pub fn main() !u8 {
|
||||
// Long-lived allocator for things that span the whole process. Only
|
||||
// actually used for the early argsAlloc and the TUI path — CLI
|
||||
// commands run under a per-invocation arena (see below).
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
const gpa_alloc = gpa.allocator();
|
||||
|
||||
const args = try std.process.argsAlloc(allocator);
|
||||
defer std.process.argsFree(allocator, args);
|
||||
const args = try std.process.argsAlloc(gpa_alloc);
|
||||
defer std.process.argsFree(gpa_alloc, args);
|
||||
|
||||
// Single buffered writer for all stdout output
|
||||
var stdout_buf: [4096]u8 = undefined;
|
||||
|
|
@ -194,19 +197,38 @@ pub fn main() !u8 {
|
|||
|
||||
const color = @import("format.zig").shouldUseColor(globals.no_color);
|
||||
|
||||
var config = zfin.Config.fromEnv(allocator);
|
||||
defer config.deinit();
|
||||
|
||||
const command = args[globals.cursor];
|
||||
const cmd_args = args[globals.cursor + 1 ..];
|
||||
|
||||
// Interactive TUI -- delegates to the TUI module (owns its own DataService).
|
||||
// Interactive TUI: long-lived, per-frame allocations benefit from a
|
||||
// real (non-arena) allocator. Runs against `gpa` directly.
|
||||
if (std.mem.eql(u8, command, "interactive") or std.mem.eql(u8, command, "i")) {
|
||||
var tui_config = zfin.Config.fromEnv(gpa_alloc);
|
||||
defer tui_config.deinit();
|
||||
try out.flush();
|
||||
try tui.run(allocator, config, globals.portfolio_path, globals.watchlist_path, cmd_args);
|
||||
try tui.run(gpa_alloc, tui_config, globals.portfolio_path, globals.watchlist_path, cmd_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ── Per-invocation arena ─────────────────────────────────────
|
||||
//
|
||||
// CLI commands do a batch of work then exit. Almost every allocation
|
||||
// they make has the same lifetime (the invocation). An arena matched
|
||||
// to that unit gives us three wins: skip per-allocation bookkeeping,
|
||||
// ignore all the per-object `defer X.deinit()` calls (they become
|
||||
// no-ops but remain correct code if the function is ever called from
|
||||
// a non-arena context), and avoid gpa's leak-checking overhead for
|
||||
// ephemeral state we're about to discard anyway.
|
||||
//
|
||||
// See models/portfolio.zig for the "match the arena to the unit of
|
||||
// work" principle. Here the unit is one `zfin <subcommand>`.
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var config = zfin.Config.fromEnv(allocator);
|
||||
defer config.deinit();
|
||||
|
||||
// Version: doesn't need DataService; uses build_info + Config paths.
|
||||
if (std.mem.eql(u8, command, "version")) {
|
||||
commands.version.run(config, cmd_args, out) catch |err| switch (err) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue