# Performance

The shape of a command.

Zinn runs when you call it, does its work and exits. These are the numbers for that round trip, and the path they take.

100 tasks, 1 comment each. CLI 0.44.0, macOS arm64.

## Read

`zinn task list --json`

One command from an agent to SQLite and back. The JSON is what the agent reads.

| Key | Value |
| --- | --- |
| p50 | 0.12 s |
| Peak memory | 82 MB |
| Output | 71.5 KB |
| Database | 471 KB |

| Phase | Time |
| --- | --- |
| Node boot | 41 ms |
| Module load | 38 ms |
| CLI | 12 ms |
| Core | 2 ms |
| SQLite | 3 ms |
| Disk | 1 ms |
| Output | 1 ms |
| Exit | 22 ms |

| Node | Kind | Metric | Value |
| --- | --- | --- | --- |
| Agent | Agent | waits | 0.12 s |
| Node runtime | Runtime | baseline | 38 MB |
| CLI | CLI | parse | 12 ms |
| Core | Core | schema | 0.8 ms |
| SQLite | SQLite | query | 2.4 ms |
| Disk | Disk | read | 512 KB |
| stdout | Output | JSON | 71.5 KB |
| Agent context | Context | tokens | 17.9k |

### Agent

The agent sends one command and waits. The wait is the whole round trip.

| Field | Value |
| --- | --- |
| command | task list --json |
| waits | 0.12 s |
| context | 71.5 KB |

In: None. Out: argv.

### Node runtime

Node starts, loads modules and holds 38 MB before Zinn reads a task.

| Field | Value |
| --- | --- |
| baseline | 38 MB |
| startup | 41 ms |
| modules | 38 ms |

In: None. Out: heap.

### CLI

The CLI parses the command and chooses the operation.

| Field | Value |
| --- | --- |
| argv | parsed |
| heap | 82 MB |
| parse | 12 ms |
| operation | task.list |

In: argv, heap. Out: operation.

### Core

Core validates the request and shapes the rows.

| Field | Value |
| --- | --- |
| operation | task.list |
| schema | 0.8 ms |
| query | SELECT |
| rows | 71.5 KB |

In: operation, rows. Out: query, rows.

### SQLite

SQLite runs the query and reads pages from the database file.

| Field | Value |
| --- | --- |
| query | SELECT |
| pages | 41 |
| rows | 71.5 KB |

In: query. Out: pages, rows.

### Disk

The database file is 471 KB at 100 tasks. The read touches 512 KB.

| Field | Value |
| --- | --- |
| pages | 512 KB |
| file | 471 KB |
| open | 0.3 ms |

In: pages. Out: None.

### stdout

The JSON is 71.5 KB for 100 tasks. The agent reads it as context.

| Field | Value |
| --- | --- |
| rows | 71.5 KB |
| write | 0.4 ms |
| JSON | 71.5 KB |

In: rows. Out: JSON.

### Agent context

About 17,900 tokens of context for 100 tasks, against a 200,000-token budget.

| Field | Value |
| --- | --- |
| JSON | 71.5 KB |
| tokens | 17.9k |
| budget | 200k |

In: JSON. Out: None.

## Write

`zinn task create`

One create. The row is small, but the write still has to reach the disk.

| Key | Value |
| --- | --- |
| p50 | 0.16 s |
| Peak memory | 81 MB |
| Output | 66 B |
| Database | 471 KB |

| Phase | Time |
| --- | --- |
| Node boot | 41 ms |
| Module load | 37 ms |
| CLI | 14 ms |
| Core | 2 ms |
| SQLite | 4 ms |
| Disk | 12 ms |
| WAL | 8 ms |
| Output | 1 ms |
| Exit | 41 ms |

| Node | Kind | Metric | Value |
| --- | --- | --- | --- |
| Agent | Agent | waits | 0.16 s |
| Node runtime | Runtime | baseline | 38 MB |
| CLI | CLI | parse | 14 ms |
| Core | Core | validate | 1.2 ms |
| SQLite | SQLite | insert | 1.8 ms |
| Disk | Disk | write | 4 KB |
| WAL | WAL | frames | 2 |
| stdout | Output | JSON | 66 B |
| Agent context | Context | tokens | 17 |

### Agent

The agent sends one create and waits for the result.

| Field | Value |
| --- | --- |
| command | task create |
| waits | 0.16 s |
| context | 66 B |

In: None. Out: argv.

### Node runtime

Node starts, loads modules and holds 38 MB before Zinn writes a row.

| Field | Value |
| --- | --- |
| baseline | 38 MB |
| startup | 41 ms |
| modules | 37 ms |

In: None. Out: heap.

### CLI

The CLI parses the flags and chooses the create operation.

| Field | Value |
| --- | --- |
| argv | parsed |
| heap | 81 MB |
| parse | 14 ms |
| operation | task.create |

In: argv, heap. Out: operation.

### Core

Core checks the fields and builds the insert.

| Field | Value |
| --- | --- |
| operation | task.create |
| validate | 1.2 ms |
| write | INSERT |
| rows | 66 B |

In: operation. Out: write, rows.

### SQLite

SQLite writes the row and appends frames to the WAL.

| Field | Value |
| --- | --- |
| write | INSERT |
| frames | 2 |
| rows | 1 |

In: write. Out: frames.

### Disk

The row is small. The file system still has to make it durable.

| Field | Value |
| --- | --- |
| frames | 4 KB |
| file | 471 KB |
| sync | 0.6 ms |
| WAL | 8 KB |

In: frames. Out: WAL.

### WAL

Two frames, 8 KB. A checkpoint folds them into the database later.

| Field | Value |
| --- | --- |
| frames | 2 |
| size | 8 KB |
| checkpoint | later |

In: frames. Out: None.

### stdout

The confirmation is 66 bytes. The agent does not need the whole task.

| Field | Value |
| --- | --- |
| rows | 66 B |
| write | 0.2 ms |
| JSON | 66 B |

In: rows. Out: JSON.

### Agent context

The create reply costs about 17 tokens of context.

| Field | Value |
| --- | --- |
| JSON | 66 B |
| tokens | 17 |
| budget | 200k |

In: JSON. Out: None.

## Install

`npm i -g @zinn-dev/cli`

One update. The tarball is small. The unpacked tree is not.

| Key | Value |
| --- | --- |
| Download | 1.4 MB |
| Unpacked | 7.3 MB |
| Files | 1,188 |
| Zinn | 226 KB |

| Phase | Time |
| --- | --- |
| Registry | 380 ms |
| npm | 210 ms |
| Unpack | 120 ms |
| Link | 20 ms |

| Node | Kind | Metric | Value |
| --- | --- | --- | --- |
| Registry | Registry | tarball | 1.3 MB |
| npm | npm | unpack | 7.2 MB |
| Disk | Disk | tree | 7.2 MB |
| Bin | Bin | link | 1 |
| npm cache | Cache | tarball | 1.3 MB |

### Registry

The tarball is 1.3 MB compressed.

| Field | Value |
| --- | --- |
| tarball | 1.3 MB |
| version | 0.44.0 |
| integrity | sha512 |

In: None. Out: tarball.

### npm

npm unpacks 7.2 MB into 1,162 files.

| Field | Value |
| --- | --- |
| tarball | 1.3 MB |
| cache | kept |
| unpack | 7.2 MB |
| tree | 1,162 files |

In: tarball. Out: cache, tree.

### Disk

The package tree lands on disk, once per update.

| Field | Value |
| --- | --- |
| tree | 7.2 MB |
| files | 1,162 |
| writes | 1,162 |

In: tree. Out: files.

### Bin

One link and a shim put zinn on the PATH.

| Field | Value |
| --- | --- |
| link | 1 |
| shim | zinn |
| version | 0.44.0 |

In: files. Out: None.

### npm cache

The tarball stays in the npm cache for the next install.

| Field | Value |
| --- | --- |
| tarball | 1.3 MB |
| hit | next time |

In: cache. Out: None.

## Commands

The 100-task fixture, one comment per task. p50, p95, peak memory and output are measured for all seven commands.

| Command | p50 | p95 | Peak memory | Output |
| --- | --- | --- | --- | --- |
| `zinn task list` | 117 ms | 124 ms | 81 MB | 6.6 KB |
| `zinn task list --json` | 117 ms | 119 ms | 82 MB | 71.5 KB |
| `zinn task view BNCH-50` | 113 ms | 115 ms | 79 MB | 737 B |
| `zinn task create` | 157 ms | 161 ms | 81 MB | 66 B |
| `zinn task move BNCH-50 TODO` | 156 ms | 159 ms | 81 MB | 62 B |
| `zinn task search amarillo BNCH` | 116 ms | 117 ms | 80 MB | 390 B |
| `zinn backup` | 155 ms | 160 ms | 80 MB | 140 B |

## Project size

The same list command as the board grows. The 100, 1,000 and 10,000-task rows are measured.

| Tasks | Database | List time | Peak memory | JSON output |
| --- | --- | --- | --- | --- |
| 100 | 471 KB | 117 ms | 81 MB | 71.5 KB |
| 1,000 | 3.1 MB | 160 ms | 93 MB | 715.9 KB |
| 10,000 | 29.0 MB | 3.45 s | 187 MB | 7.2 MB |

## Storage

An empty database is 123 KB. A task adds about 1.6 KB and a comment about 1.3 KB. At 10,000 tasks the file is 29.0 MB.

The published packages download 1.4 MB, unpack to 7.3 MB in 1,188 files, and Zinn's own packages are 226 KB of the download.

## Method

Measured with CLI 0.44.0 and the packages it installs. Command times are medians of 30 runs, p95 is the nearest rank of those 30, and peak memory is the median per-run peak RSS from hyperfine. Each task has a 40-character title, a 200-character description and one 200-character comment.

Node timings and install timings are placeholders. Estimated processor energy above idle, on an M4 MacBook Pro. The read flow uses about 0.20 mWh above idle, and Node accounts for 0.06 mWh.
