From d78a2530da91b76625b71c2aeaf3293abc6c3a4b Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 6 May 2026 09:42:43 +0300 Subject: move demo/ to docs/tutorial/, commit assets, consolidate TUI docs - demo/ renamed to docs/tutorial/ (tapes, scripts, TUTORIAL.md) - docs/tutorial/assets/ added to git (51 MB of GIFs + PNGs); removed /demo/assets/ from .gitignore so images render on Codeberg - docs/tui-reference.md removed; its hotkey tables merged into a new "Hotkey Quick Reference" section at the end of TUTORIAL.md - TUTORIAL.md: updated install section (mage buildDocker, no GOTOOLCHAIN=auto), fixed README relative path (../../README.md), updated internal tapes/scripts/assets path prose - README.md: updated all demo/ image paths and links to docs/tutorial/; TUI and recording-modes links now point to TUTORIAL.md anchors - AGENTS.md: updated demo/ references to docs/tutorial/ - Magefile.go: updated demoDir/demoTapesDir/demoScriptsDir/demoRunTape/ demoSudoKeepers constants to docs/tutorial/ paths Co-Authored-By: Claude Sonnet 4.6 --- docs/tui-reference.md | 175 --------------- docs/tutorial/TUTORIAL.md | 245 +++++++++++++++++++++ docs/tutorial/assets/00-hero-flamegraph.png | Bin 0 -> 156731 bytes docs/tutorial/assets/00-logo.png | Bin 0 -> 332693 bytes docs/tutorial/assets/01-launch.gif | Bin 0 -> 4244461 bytes docs/tutorial/assets/02-overview-tab.gif | Bin 0 -> 263106 bytes docs/tutorial/assets/03-syscalls-tab.gif | Bin 0 -> 1091628 bytes docs/tutorial/assets/04-files-tab.gif | Bin 0 -> 1577094 bytes docs/tutorial/assets/05-processes-tab.gif | Bin 0 -> 1034718 bytes docs/tutorial/assets/06-latency-gaps-tab.gif | Bin 0 -> 300466 bytes docs/tutorial/assets/07-stream-live.gif | Bin 0 -> 7063227 bytes docs/tutorial/assets/08-stream-pause-filter.gif | Bin 0 -> 5796596 bytes docs/tutorial/assets/09-stream-regex-search.gif | Bin 0 -> 5367913 bytes docs/tutorial/assets/10-stream-csv-export.gif | Bin 0 -> 4671995 bytes docs/tutorial/assets/11-pid-tid-probe.gif | Bin 0 -> 3584783 bytes docs/tutorial/assets/12-parquet-recording.gif | Bin 0 -> 2353504 bytes docs/tutorial/assets/13-tui-flamegraph.gif | Bin 0 -> 6333590 bytes docs/tutorial/assets/13a-order-by-process.png | Bin 0 -> 231292 bytes docs/tutorial/assets/13b-order-by-path.png | Bin 0 -> 218540 bytes docs/tutorial/assets/13c-order-by-syscall.png | Bin 0 -> 255276 bytes docs/tutorial/assets/13d-order-by-pid.png | Bin 0 -> 183662 bytes .../tutorial/assets/13e-order-by-process-paths.png | Bin 0 -> 214308 bytes docs/tutorial/assets/14-headless-modes.gif | Bin 0 -> 4791550 bytes docs/tutorial/assets/screenshot-dashboard.png | Bin 0 -> 173558 bytes docs/tutorial/assets/screenshot-files-grouped.png | Bin 0 -> 207344 bytes docs/tutorial/assets/screenshot-flamegraph.png | Bin 0 -> 171887 bytes docs/tutorial/assets/screenshot-latency.png | Bin 0 -> 105203 bytes docs/tutorial/assets/screenshot-overview.png | Bin 0 -> 167438 bytes docs/tutorial/assets/screenshot-pidpicker-open.png | Bin 0 -> 122673 bytes docs/tutorial/assets/screenshot-pidpicker.png | Bin 0 -> 122249 bytes docs/tutorial/assets/screenshot-probes.png | Bin 0 -> 157287 bytes docs/tutorial/assets/screenshot-processes.png | Bin 0 -> 191556 bytes .../assets/screenshot-recording-active.png | Bin 0 -> 188855 bytes docs/tutorial/assets/screenshot-stream-export.png | Bin 0 -> 28883 bytes .../tutorial/assets/screenshot-stream-filtered.png | Bin 0 -> 198074 bytes docs/tutorial/assets/screenshot-stream-live.png | Bin 0 -> 29593 bytes docs/tutorial/assets/screenshot-stream-search.png | Bin 0 -> 169878 bytes docs/tutorial/assets/screenshot-syscalls.png | Bin 0 -> 226128 bytes docs/tutorial/assets/screenshot-tidpicker.png | Bin 0 -> 121954 bytes docs/tutorial/scripts/run-tape.sh | 52 +++++ docs/tutorial/scripts/sudo-keepalive.sh | 13 ++ docs/tutorial/scripts/workload.sh | 77 +++++++ docs/tutorial/tapes/01-launch.tape | 23 ++ docs/tutorial/tapes/02-overview-tab.tape | 23 ++ docs/tutorial/tapes/03-syscalls-tab.tape | 36 +++ docs/tutorial/tapes/04-files-tab.tape | 32 +++ docs/tutorial/tapes/05-processes-tab.tape | 30 +++ docs/tutorial/tapes/06-latency-gaps-tab.tape | 22 ++ docs/tutorial/tapes/07-stream-live.tape | 22 ++ docs/tutorial/tapes/08-stream-pause-filter.tape | 46 ++++ docs/tutorial/tapes/09-stream-regex-search.tape | 40 ++++ docs/tutorial/tapes/10-stream-csv-export.tape | 28 +++ docs/tutorial/tapes/11-pid-tid-probe.tape | 41 ++++ docs/tutorial/tapes/12-parquet-recording.tape | 28 +++ docs/tutorial/tapes/13-tui-flamegraph.tape | 22 ++ docs/tutorial/tapes/14-headless-modes.tape | 38 ++++ 56 files changed, 818 insertions(+), 175 deletions(-) delete mode 100644 docs/tui-reference.md create mode 100644 docs/tutorial/TUTORIAL.md create mode 100644 docs/tutorial/assets/00-hero-flamegraph.png create mode 100644 docs/tutorial/assets/00-logo.png create mode 100644 docs/tutorial/assets/01-launch.gif create mode 100644 docs/tutorial/assets/02-overview-tab.gif create mode 100644 docs/tutorial/assets/03-syscalls-tab.gif create mode 100644 docs/tutorial/assets/04-files-tab.gif create mode 100644 docs/tutorial/assets/05-processes-tab.gif create mode 100644 docs/tutorial/assets/06-latency-gaps-tab.gif create mode 100644 docs/tutorial/assets/07-stream-live.gif create mode 100644 docs/tutorial/assets/08-stream-pause-filter.gif create mode 100644 docs/tutorial/assets/09-stream-regex-search.gif create mode 100644 docs/tutorial/assets/10-stream-csv-export.gif create mode 100644 docs/tutorial/assets/11-pid-tid-probe.gif create mode 100644 docs/tutorial/assets/12-parquet-recording.gif create mode 100644 docs/tutorial/assets/13-tui-flamegraph.gif create mode 100644 docs/tutorial/assets/13a-order-by-process.png create mode 100644 docs/tutorial/assets/13b-order-by-path.png create mode 100644 docs/tutorial/assets/13c-order-by-syscall.png create mode 100644 docs/tutorial/assets/13d-order-by-pid.png create mode 100644 docs/tutorial/assets/13e-order-by-process-paths.png create mode 100644 docs/tutorial/assets/14-headless-modes.gif create mode 100644 docs/tutorial/assets/screenshot-dashboard.png create mode 100644 docs/tutorial/assets/screenshot-files-grouped.png create mode 100644 docs/tutorial/assets/screenshot-flamegraph.png create mode 100644 docs/tutorial/assets/screenshot-latency.png create mode 100644 docs/tutorial/assets/screenshot-overview.png create mode 100644 docs/tutorial/assets/screenshot-pidpicker-open.png create mode 100644 docs/tutorial/assets/screenshot-pidpicker.png create mode 100644 docs/tutorial/assets/screenshot-probes.png create mode 100644 docs/tutorial/assets/screenshot-processes.png create mode 100644 docs/tutorial/assets/screenshot-recording-active.png create mode 100644 docs/tutorial/assets/screenshot-stream-export.png create mode 100644 docs/tutorial/assets/screenshot-stream-filtered.png create mode 100644 docs/tutorial/assets/screenshot-stream-live.png create mode 100644 docs/tutorial/assets/screenshot-stream-search.png create mode 100644 docs/tutorial/assets/screenshot-syscalls.png create mode 100644 docs/tutorial/assets/screenshot-tidpicker.png create mode 100755 docs/tutorial/scripts/run-tape.sh create mode 100755 docs/tutorial/scripts/sudo-keepalive.sh create mode 100755 docs/tutorial/scripts/workload.sh create mode 100644 docs/tutorial/tapes/01-launch.tape create mode 100644 docs/tutorial/tapes/02-overview-tab.tape create mode 100644 docs/tutorial/tapes/03-syscalls-tab.tape create mode 100644 docs/tutorial/tapes/04-files-tab.tape create mode 100644 docs/tutorial/tapes/05-processes-tab.tape create mode 100644 docs/tutorial/tapes/06-latency-gaps-tab.tape create mode 100644 docs/tutorial/tapes/07-stream-live.tape create mode 100644 docs/tutorial/tapes/08-stream-pause-filter.tape create mode 100644 docs/tutorial/tapes/09-stream-regex-search.tape create mode 100644 docs/tutorial/tapes/10-stream-csv-export.tape create mode 100644 docs/tutorial/tapes/11-pid-tid-probe.tape create mode 100644 docs/tutorial/tapes/12-parquet-recording.tape create mode 100644 docs/tutorial/tapes/13-tui-flamegraph.tape create mode 100644 docs/tutorial/tapes/14-headless-modes.tape (limited to 'docs') diff --git a/docs/tui-reference.md b/docs/tui-reference.md deleted file mode 100644 index d6a7266..0000000 --- a/docs/tui-reference.md +++ /dev/null @@ -1,175 +0,0 @@ -# TUI Reference - -## TUI Flamegraphs - -Flamegraphs are available only inside the TUI dashboard. -Use `-fields` to change the stack order and `-count` to choose the metric. -The default stack order is `comm,path,tracepoint` (bottom to top). - -## Recording Modes - -`ior` has four distinct output flows: - -| Mode | How to use it | What it writes | Filter behavior | -| --- | --- | --- | --- | -| TUI dashboard | default startup | nothing continuously; data stays in memory unless you export | current TUI/global filters drive what you see | -| TUI CSV snapshot export | press `e` in the dashboard | one `ior-stream-.csv` snapshot of the current filtered stream view | exports only the currently filtered in-memory rows | -| Headless `.ior.zst` export | start with `-flamegraph -name ` | one aggregated native trace artifact written at shutdown | no TUI filter stack; this is the native trace/integration workflow | -| Parquet recording | press `R` in the TUI, or start with `-parquet ` | a streaming Parquet file of traced syscall rows | TUI mode records rows that pass the active TUI filter; headless `-parquet` records all traced rows | - -Important distinction: - -- `.ior.zst` output is an aggregated native artifact, not a row-by-row event log. -- CSV export is a point-in-time snapshot of the ring buffer. -- Parquet recording is a streaming capture from start to stop. -- The ring buffer is capped, so CSV export is not a replacement for Parquet recording or `.ior.zst` output. - -### Headless Native `.ior.zst` Output - -Use `-flamegraph` when you want the native `ior` trace artifact instead of a streaming row log: - -```shell -sudo ./ior -flamegraph -name trace-run -duration 60 -``` - -Native `.ior.zst` behavior: - -- writes one `*.ior.zst` file when the run ends -- stores aggregated counters for repeated syscall/path/process combinations -- is intended for `ior`'s native flamegraph and integration-style workflows -- does not preserve one output row per traced syscall - -### TUI Parquet Recording - -Start a recording from the dashboard with `R`. - -- First `R`: open a filename prompt (`ior-recording-.parquet` by default). -- `Enter`: start recording to that file. -- Second `R`: stop and finalize the active Parquet file. -- Recording stops automatically when you quit the TUI or reselect PID/TID/session scope. - -Lifecycle details: - -- TUI recording uses the active TUI global filter at emission time. -- If a filter change restarts tracing, the recorder stays alive and continues writing matching rows after the restart. -- The dashboard footer shows the active recording path or the last recording error. - -### Headless Parquet Recording - -Use `-parquet` to skip the TUI and stream traced syscall rows directly to a Parquet file: - -```shell -sudo ./ior -parquet trace.parquet -duration 60 -``` - -Headless Parquet mode behavior: - -- skips the TUI completely -- records all traced rows -- rejects content filters such as `-comm`, `-path`, `-pid`, and `-tid` -- cannot be combined with `-plain`, `-flamegraph`, `--testflames`, or `--testliveflames` - -Use headless mode when you want a full recording, and TUI mode when you want interactive filtering plus optional start/stop recording from the dashboard. - -### Choosing Between `.ior.zst` and Parquet - -| Question | Native `.ior.zst` | Parquet | -| --- | --- | --- | -| Data shape | aggregated counters | one row per traced syscall | -| Write pattern | collect in memory, write one compressed artifact at the end | stream rows continuously while recording | -| Best for | `ior`-native trace artifacts, flamegraph workflows, integration assertions | offline analysis in other tools, long captures, preserving per-event detail | -| Relative write cost | usually lower because repeated events are folded together before file write | usually higher because each traced row is serialized | -| Detail retained | loses original row order and per-event granularity | keeps per-event timing and syscall fields | - -Rule of thumb: - -- choose `.ior.zst` when you want the native `ior` artifact and do not need every traced syscall row preserved -- choose Parquet when you want a full event stream for downstream analysis outside `ior` - -## TUI Navigation - -The TUI has an in-screen help panel (toggle with **H**) that lists all available -keys. Use it to discover shortcuts without consulting this document. - -Dashboard tabs: - -- **tab** / **shift+tab** — next / previous tab -- **1** — Overview -- **2** — Syscalls -- **3** — Files -- **4** — Processes -- **5** — Latency+Gaps -- **6** — Stream - -The TUI has two key scopes: - -- Global hotkeys: available from any dashboard screen. -- Dashboard hotkeys: behavior that depends on the active tab (especially `6:Stream`). - -### Global Hotkeys - -- `tab` / `shift+tab`: cycle tabs. -- `1`–`6`: jump to tab by number (`7` is an alias for `6`). -- `e`: export filtered stream rows to CSV (`ior-stream-.csv`). -- `R`: start or stop Parquet recording. -- `p`: re-open process selector (PID selection flow). -- `t`: open TID selector flow. -- `o`: open probe selection/toggling dialog. -- `r`: refresh dashboard snapshot. -- `H`: toggle bottom help sections on/off. -- `q` or `ctrl+c`: quit. - -### Dashboard / Tab-Specific Hotkeys - -- `d` in `3:Files`: toggle directory-grouped files view. -- `s` in sortable tabs (`2:Syscalls`, `3:Files`, `4:Processes`): sort by selected column. -- `S` in sortable tabs: reverse-sort by selected column. -- `j/k` or `up/down` in list tabs: scroll list. - -`left/right` and `h/l` do not switch tabs. In `6:Stream` paused mode they move the selected column. - -### 6:Stream Hotkeys and Behavior - -`6:Stream` has two modes: - -- Live mode (`paused=false`): rows update continuously. -- Pause mode (`paused=true`): selection/cell/filter/search/export workflows are enabled. - -Core controls: - -- `space`: toggle live/pause. -- `g`/`G`: jump to top/tail. -- `c`: clear stream filters. -- `f`: open advanced filter modal. -- `j/k` or `up/down`: move selected row (pause) or scroll (live). -- `left/right` or `h/l`: move selected column in pause mode. - -#### Enter-Based Filter Stack (Pause Mode) - -In pause mode, `enter` on the selected cell pushes a filter onto a stack and -immediately re-filters the current ring buffer snapshot. Filters are stackable. - -- String columns use case-insensitive substring match: - - `Comm` → `comm~` - - `Syscall` → `syscall~` - - `File` → `file~` -- Numeric exact match: `PID`, `TID`, `FD`, `Ret`, `Bytes` -- Numeric threshold (`>=`): `Latency` → `latency>=selected_value`, `Gap` → `gap>=selected_value` - -`esc` in pause mode pops the most recent filter (LIFO); repeated `esc` undoes -all stacked filters. - -#### Regex Search (Pause Mode) - -- `/`: search forward; `?`: search backward. -- Search checks all stream columns and wraps around the ring buffer. -- `n` / `N`: next / previous match. - -#### Stream CSV Export (Pause Mode) - -- `x`: quick export filtered stream rows to CSV. -- `X`: export with filename prompt. -- `E`: open last stream-exported CSV in foreground editor (`EDITOR` → `VISUAL` → `SUDO_EDITOR` → `hx` → `vi`). - -`e` (global) exports a fresh filtered snapshot even outside paused mode; `x`/`X` -export the exact paused view. diff --git a/docs/tutorial/TUTORIAL.md b/docs/tutorial/TUTORIAL.md new file mode 100644 index 0000000..e53013a --- /dev/null +++ b/docs/tutorial/TUTORIAL.md @@ -0,0 +1,245 @@ +# I/O Riot NG: a guided tour + +This tutorial walks through every major surface of `ior` — the dashboard tabs, the live stream, recording, headless modes, and the in-TUI flamegraph — using short animated GIFs so you can *see* what the keys actually do. + +Every GIF in this document is regenerated from a [VHS](https://github.com/charmbracelet/vhs) tape under [`demo/tapes/`](./tapes). To rebuild them all, run `sudo -v && mage demo` (see [Regenerating the demo](#regenerating-the-demo)). + +## Contents + +1. [Installing ior](#installing-ior) +2. [First launch: the PID picker](#first-launch-the-pid-picker) +3. [Touring the dashboard tabs](#touring-the-dashboard-tabs) + - [1 · Flamegraph (default landing tab)](#1--flamegraph-default-landing-tab) + - [2 · Overview](#2--overview) + - [3 · Syscalls](#3--syscalls) + - [4 · Files](#4--files) + - [5 · Processes](#5--processes) + - [6 · Latency + Gaps](#6--latency--gaps) + - [7 · Stream](#7--stream) +4. [Mastering the Stream tab](#mastering-the-stream-tab) + - [Pause + stacked filters](#pause--stacked-filters) + - [Regex search](#regex-search) + - [CSV export](#csv-export) +5. [Choosing what to trace](#choosing-what-to-trace) +6. [Recording for offline analysis](#recording-for-offline-analysis) + - [TUI Parquet recording](#tui-parquet-recording) + - [Headless modes](#headless-modes) +7. [Regenerating the demo](#regenerating-the-demo) + +## Installing ior + +See the [main README](../../README.md) for full install steps. The quickest path from any Docker-capable Linux host: + +```shell +git clone https://codeberg.org/snonux/ior ~/git/ior +cd ~/git/ior +mage buildDocker # builds inside a Rocky 9 container, ~15 min on first run +``` + +For a native build (libbpfgo must be cloned alongside the repo first — see the README): + +```shell +mage all +``` + +ior needs `CAP_BPF`, so every invocation below uses `sudo`. + +The build dance only has to happen once: the resulting `ior` binary is fully statically linked and uses CO-RE, so the same binary runs on any BTF-enabled Linux kernel without recompilation. See the [Compile once, run everywhere](../../README.md#compile-once-run-everywhere) section for details. + +## First launch: the PID picker + +`sudo ./ior` starts with the **PID picker**. The cursor is on **All PIDs**, so pressing `Enter` traces the whole system. Type into the filter box to narrow the list by PID, comm, or cmdline; arrow keys move the selection. + +![Cold start: PID picker, then the dashboard appears](./assets/01-launch.gif) + +The same picker can be re-opened later from the dashboard with `p`. + +![PID picker default state](./assets/screenshot-pidpicker.png) + +## Touring the dashboard tabs + +The dashboard has seven tabs, addressable by number key. The default landing tab is **Flamegraph**. `tab` / `shift+tab` step forward / back. + +| Key | Tab | What it shows | +|-----|-------------------|--------------------------------------------------------------------------| +| `1` | Flamegraph (`Flm`)| Live FlameGraph of the configured stack (`comm`/`path`/`tracepoint`) | +| `2` | Overview (`Ovr`) | Sparkline + top syscalls + top paths summary | +| `3` | Syscalls (`Sys`) | Sortable per-syscall counters, latency, byte volume | +| `4` | Files (`Fil`) | Per-path counters; `d` toggles directory grouping | +| `5` | Processes (`Pro`) | Per-process / per-comm counters | +| `6` | Latency (`Lat`) | Latency + inter-syscall gap histograms | +| `7` | Stream (`Str`) | Live tail of individual traced events | + +### 1 · Flamegraph (default landing tab) + +The first thing you see after dismissing the PID picker is the **live flamegraph**. Bars grow as new events come in. `o` cycles the stack ordering (e.g. `comm/path/tracepoint` ↔ `comm/tracepoint/path`); `b` toggles the size metric (event count vs. duration vs. gap). + +![Live flamegraph rebuilding from real workload](./assets/13-tui-flamegraph.gif) + +### 2 · Overview + +Press `2`. The Overview tab is the at-a-glance view: a sparkline of recent event volume, the top syscalls, and the top paths. + +![Overview tab populating](./assets/02-overview-tab.gif) + +### 3 · Syscalls + +Press `3`. A sortable table of every traced syscall (count, average latency, total bytes). `j` / `k` (or arrow keys) scroll the rows; `←` / `→` move the selected column; `s` sorts by the selected column using its default direction; `S` reverses. + +![Syscalls table with sort + reverse-sort](./assets/03-syscalls-tab.gif) + +### 4 · Files + +Press `4`. Per-path counters. The most useful key here is `d`, which toggles **directory grouping** — paths roll up into their parent directory, which is essential when one process touches thousands of files in `/usr/share/...`. + +![Files tab toggling directory grouping](./assets/04-files-tab.gif) + +### 5 · Processes + +Press `5`. Per-process / per-comm view. `S` reverse-sorts; combine with `←` / `→` to pick a column. + +![Processes tab](./assets/05-processes-tab.gif) + +### 6 · Latency + Gaps + +Press `6`. Two histograms: syscall **latency** (how long the syscall ran) and the inter-syscall **gap** (idle time on the same thread between syscalls). The big-write workload running in the background spreads the latency distribution noticeably. + +![Latency + gap histograms](./assets/06-latency-gaps-tab.gif) + +### 7 · Stream + +Press `7`. A live tail of every traced event row — comm, PID, TID, syscall, file, FD, return value, bytes, latency, gap. This is the workhorse view; the next section explores it in depth. + +![Stream tab live-tailing rows](./assets/07-stream-live.gif) + +## Mastering the Stream tab + +Stream has two modes: **Live** (rows scroll past) and **Pause** (`space` toggles). Almost everything interesting happens in pause mode. + +### Pause + stacked filters + +In pause mode, navigate with `j`/`k` (rows) and `←` / `→` (columns). Pressing `Enter` on the selected cell **pushes a new filter onto a stack** and immediately re-filters the ring buffer. Filters are stackable, so you can drill down — first by `Comm`, then by `Syscall`, then by `File`. `Esc` pops the most recent filter (LIFO); keep hitting `Esc` to undo all the way back. + +![Pause, push two filters, undo with Esc](./assets/08-stream-pause-filter.gif) + +The filter is reflected in the bottom status line, and matches the same syntax you'd type by hand: `comm~bash`, `syscall~openat`, `latency>=100000`, etc. + +### Regex search + +`/` opens a forward regex prompt; `?` opens a backward one. `n` jumps to the next match in the same direction; `N` reverses. The search runs against every column on every row in the ring buffer and wraps at the end. + +![Regex search with /, n, n, then ?](./assets/09-stream-regex-search.gif) + +### CSV export + +Three keys, three flavours: + +- `e` — quick export of the **current TUI-filter snapshot** to `ior-stream-.csv` in the current working directory. Works from any tab, not just Stream. +- `x` — quick export of the **paused stream view** specifically (preserves your filter stack). +- `X` — same as `x`, but prompts for a filename first. +- `E` — open the most recent stream-exported CSV in your `$EDITOR` (`hx` / `vi` fallback). + +![Press 'e', then ls the resulting CSV](./assets/10-stream-csv-export.gif) + +If you don't want CSV export at all, start ior with `-tuiExport=false`; the help footer hides the export keys and `e` becomes a no-op. + +## Choosing what to trace + +Three modal pickers reshape what the rest of the TUI sees: + +- `p` — **PID picker** (re-opens the launch picker). +- `t` — **TID picker** for thread-level focus. +- `o` — **Probes** dialog: enable / disable individual syscall tracepoints. + +![PID, TID, and probe pickers](./assets/11-pid-tid-probe.gif) + +Restricting to a single PID is also exposed as a CLI flag (`-pid `), as is comm/path filtering (`-comm`, `-path`). Tracepoint subsetting on the command line uses `-tps ` / `-tpsExclude `. + +## Recording for offline analysis + +ior has three persistence flows; each solves a different problem. + +| Flow | How | What you get | +|------------------------|----------------------------------------------|---------------------------------------------------------| +| TUI Parquet recording | `R` from the dashboard | streaming Parquet of every row that passes your filter | +| Headless `.ior.zst` | `sudo ./ior -flamegraph -name ` | one aggregated native trace artifact (bandwidth-cheap) | +| Headless Parquet | `sudo ./ior -parquet trace.parquet` | streaming Parquet, full firehose, no TUI | +| Plain CSV | `sudo ./ior -plain` | one CSV row per event on stdout | + +### TUI Parquet recording + +Press `R` in the dashboard, accept the default filename (`ior-recording-.parquet`) with `Enter`, and rows start streaming to disk. The footer shows the active recording path (or the last error). Press `R` again to stop. + +![Start, run, and stop a parquet recording](./assets/12-parquet-recording.gif) + +The recorder follows your *current* TUI global filter — narrow with `p`/`t`/`o` first if you want a focused capture. + +### Headless modes + +For unattended captures or scripting, skip the TUI entirely. The demo runs all three back-to-back, capped with `-duration` so each terminates on its own. + +![Three headless flows in one tape](./assets/14-headless-modes.gif) + +`-flamegraph` writes one aggregated `.ior.zst` artifact at shutdown — ideal for `ior`'s native flamegraph and integration workflows. `-parquet` streams every row, so the file grows continuously. `-plain` is the lightest weight: CSV to stdout you can pipe into anything. + +## Regenerating the demo + +The whole asset pipeline is reproducible: + +```shell +mage installDemoTools # one-time: VHS via go install + ttyd via dnf +sudo -v # warm the sudo timestamp once +mage demo # regen all 14 GIFs + screenshots (~10 min) +``` + +Or rebuild a single tape after editing it: + +```shell +TAPE=07-stream-live mage demoOne +``` + +Tapes live in [`tapes/`](./tapes), the background workload that drives them is [`scripts/workload.sh`](./scripts/workload.sh), and the resulting assets land in [`assets/`](./assets). VHS records headlessly under `ttyd` + Chromium — no real terminal window opens, so `mage demo` is safe to run in the background while you keep working. + +## Hotkey Quick Reference + +### Global keys + +| Key | Action | +|-----|--------| +| `tab` / `shift+tab` | next / previous tab | +| `1`–`6` (`7` = alias for `6`) | jump to tab by number | +| `H` | toggle bottom help panel | +| `e` | export filtered stream snapshot to CSV | +| `R` | start / stop Parquet recording | +| `p` | re-open PID picker | +| `t` | open TID picker | +| `o` | open probe selection dialog | +| `r` | refresh dashboard snapshot | +| `q` / `ctrl+c` | quit | + +### Tab-specific keys (`2:Syscalls`, `3:Files`, `4:Processes`) + +| Key | Action | +|-----|--------| +| `s` | sort by selected column (default direction) | +| `S` | reverse-sort by selected column | +| `j`/`k` or `↑`/`↓` | scroll list | +| `d` (Files only) | toggle directory grouping | + +### Stream tab (`7:Stream`) + +| Key | Action | +|-----|--------| +| `space` | toggle live / pause mode | +| `g` / `G` | jump to top / tail | +| `j`/`k` or `↑`/`↓` | move row (pause) / scroll (live) | +| `←`/`→` or `h`/`l` | move selected column (pause only) | +| `enter` | push cell value as filter (pause) | +| `esc` | pop most recent filter (LIFO) | +| `c` | clear all stream filters | +| `f` | open advanced filter modal | +| `/` / `?` | regex search forward / backward | +| `n` / `N` | next / previous search match | +| `x` | quick CSV export of paused view | +| `X` | CSV export with filename prompt | +| `E` | open last CSV export in `$EDITOR` | diff --git a/docs/tutorial/assets/00-hero-flamegraph.png b/docs/tutorial/assets/00-hero-flamegraph.png new file mode 100644 index 0000000..d409e79 Binary files /dev/null and b/docs/tutorial/assets/00-hero-flamegraph.png differ diff --git a/docs/tutorial/assets/00-logo.png b/docs/tutorial/assets/00-logo.png new file mode 100644 index 0000000..d2da30c Binary files /dev/null and b/docs/tutorial/assets/00-logo.png differ diff --git a/docs/tutorial/assets/01-launch.gif b/docs/tutorial/assets/01-launch.gif new file mode 100644 index 0000000..978b95e Binary files /dev/null and b/docs/tutorial/assets/01-launch.gif differ diff --git a/docs/tutorial/assets/02-overview-tab.gif b/docs/tutorial/assets/02-overview-tab.gif new file mode 100644 index 0000000..56f0e98 Binary files /dev/null and b/docs/tutorial/assets/02-overview-tab.gif differ diff --git a/docs/tutorial/assets/03-syscalls-tab.gif b/docs/tutorial/assets/03-syscalls-tab.gif new file mode 100644 index 0000000..47c4029 Binary files /dev/null and b/docs/tutorial/assets/03-syscalls-tab.gif differ diff --git a/docs/tutorial/assets/04-files-tab.gif b/docs/tutorial/assets/04-files-tab.gif new file mode 100644 index 0000000..af18828 Binary files /dev/null and b/docs/tutorial/assets/04-files-tab.gif differ diff --git a/docs/tutorial/assets/05-processes-tab.gif b/docs/tutorial/assets/05-processes-tab.gif new file mode 100644 index 0000000..a6beed1 Binary files /dev/null and b/docs/tutorial/assets/05-processes-tab.gif differ diff --git a/docs/tutorial/assets/06-latency-gaps-tab.gif b/docs/tutorial/assets/06-latency-gaps-tab.gif new file mode 100644 index 0000000..b0d9c81 Binary files /dev/null and b/docs/tutorial/assets/06-latency-gaps-tab.gif differ diff --git a/docs/tutorial/assets/07-stream-live.gif b/docs/tutorial/assets/07-stream-live.gif new file mode 100644 index 0000000..af742bd Binary files /dev/null and b/docs/tutorial/assets/07-stream-live.gif differ diff --git a/docs/tutorial/assets/08-stream-pause-filter.gif b/docs/tutorial/assets/08-stream-pause-filter.gif new file mode 100644 index 0000000..7821cf7 Binary files /dev/null and b/docs/tutorial/assets/08-stream-pause-filter.gif differ diff --git a/docs/tutorial/assets/09-stream-regex-search.gif b/docs/tutorial/assets/09-stream-regex-search.gif new file mode 100644 index 0000000..73e068b Binary files /dev/null and b/docs/tutorial/assets/09-stream-regex-search.gif differ diff --git a/docs/tutorial/assets/10-stream-csv-export.gif b/docs/tutorial/assets/10-stream-csv-export.gif new file mode 100644 index 0000000..aa5bb3b Binary files /dev/null and b/docs/tutorial/assets/10-stream-csv-export.gif differ diff --git a/docs/tutorial/assets/11-pid-tid-probe.gif b/docs/tutorial/assets/11-pid-tid-probe.gif new file mode 100644 index 0000000..f7f96c7 Binary files /dev/null and b/docs/tutorial/assets/11-pid-tid-probe.gif differ diff --git a/docs/tutorial/assets/12-parquet-recording.gif b/docs/tutorial/assets/12-parquet-recording.gif new file mode 100644 index 0000000..b9baab3 Binary files /dev/null and b/docs/tutorial/assets/12-parquet-recording.gif differ diff --git a/docs/tutorial/assets/13-tui-flamegraph.gif b/docs/tutorial/assets/13-tui-flamegraph.gif new file mode 100644 index 0000000..71aece3 Binary files /dev/null and b/docs/tutorial/assets/13-tui-flamegraph.gif differ diff --git a/docs/tutorial/assets/13a-order-by-process.png b/docs/tutorial/assets/13a-order-by-process.png new file mode 100644 index 0000000..8a469bf Binary files /dev/null and b/docs/tutorial/assets/13a-order-by-process.png differ diff --git a/docs/tutorial/assets/13b-order-by-path.png b/docs/tutorial/assets/13b-order-by-path.png new file mode 100644 index 0000000..3518412 Binary files /dev/null and b/docs/tutorial/assets/13b-order-by-path.png differ diff --git a/docs/tutorial/assets/13c-order-by-syscall.png b/docs/tutorial/assets/13c-order-by-syscall.png new file mode 100644 index 0000000..3eb5058 Binary files /dev/null and b/docs/tutorial/assets/13c-order-by-syscall.png differ diff --git a/docs/tutorial/assets/13d-order-by-pid.png b/docs/tutorial/assets/13d-order-by-pid.png new file mode 100644 index 0000000..0d56f12 Binary files /dev/null and b/docs/tutorial/assets/13d-order-by-pid.png differ diff --git a/docs/tutorial/assets/13e-order-by-process-paths.png b/docs/tutorial/assets/13e-order-by-process-paths.png new file mode 100644 index 0000000..ccd450a Binary files /dev/null and b/docs/tutorial/assets/13e-order-by-process-paths.png differ diff --git a/docs/tutorial/assets/14-headless-modes.gif b/docs/tutorial/assets/14-headless-modes.gif new file mode 100644 index 0000000..cf245f4 Binary files /dev/null and b/docs/tutorial/assets/14-headless-modes.gif differ diff --git a/docs/tutorial/assets/screenshot-dashboard.png b/docs/tutorial/assets/screenshot-dashboard.png new file mode 100644 index 0000000..0eee11f Binary files /dev/null and b/docs/tutorial/assets/screenshot-dashboard.png differ diff --git a/docs/tutorial/assets/screenshot-files-grouped.png b/docs/tutorial/assets/screenshot-files-grouped.png new file mode 100644 index 0000000..b2a206a Binary files /dev/null and b/docs/tutorial/assets/screenshot-files-grouped.png differ diff --git a/docs/tutorial/assets/screenshot-flamegraph.png b/docs/tutorial/assets/screenshot-flamegraph.png new file mode 100644 index 0000000..ae79335 Binary files /dev/null and b/docs/tutorial/assets/screenshot-flamegraph.png differ diff --git a/docs/tutorial/assets/screenshot-latency.png b/docs/tutorial/assets/screenshot-latency.png new file mode 100644 index 0000000..43b6cd8 Binary files /dev/null and b/docs/tutorial/assets/screenshot-latency.png differ diff --git a/docs/tutorial/assets/screenshot-overview.png b/docs/tutorial/assets/screenshot-overview.png new file mode 100644 index 0000000..eac3138 Binary files /dev/null and b/docs/tutorial/assets/screenshot-overview.png differ diff --git a/docs/tutorial/assets/screenshot-pidpicker-open.png b/docs/tutorial/assets/screenshot-pidpicker-open.png new file mode 100644 index 0000000..22a7b93 Binary files /dev/null and b/docs/tutorial/assets/screenshot-pidpicker-open.png differ diff --git a/docs/tutorial/assets/screenshot-pidpicker.png b/docs/tutorial/assets/screenshot-pidpicker.png new file mode 100644 index 0000000..4b8f025 Binary files /dev/null and b/docs/tutorial/assets/screenshot-pidpicker.png differ diff --git a/docs/tutorial/assets/screenshot-probes.png b/docs/tutorial/assets/screenshot-probes.png new file mode 100644 index 0000000..df0664a Binary files /dev/null and b/docs/tutorial/assets/screenshot-probes.png differ diff --git a/docs/tutorial/assets/screenshot-processes.png b/docs/tutorial/assets/screenshot-processes.png new file mode 100644 index 0000000..c1873d2 Binary files /dev/null and b/docs/tutorial/assets/screenshot-processes.png differ diff --git a/docs/tutorial/assets/screenshot-recording-active.png b/docs/tutorial/assets/screenshot-recording-active.png new file mode 100644 index 0000000..e50d588 Binary files /dev/null and b/docs/tutorial/assets/screenshot-recording-active.png differ diff --git a/docs/tutorial/assets/screenshot-stream-export.png b/docs/tutorial/assets/screenshot-stream-export.png new file mode 100644 index 0000000..921330c Binary files /dev/null and b/docs/tutorial/assets/screenshot-stream-export.png differ diff --git a/docs/tutorial/assets/screenshot-stream-filtered.png b/docs/tutorial/assets/screenshot-stream-filtered.png new file mode 100644 index 0000000..7b85470 Binary files /dev/null and b/docs/tutorial/assets/screenshot-stream-filtered.png differ diff --git a/docs/tutorial/assets/screenshot-stream-live.png b/docs/tutorial/assets/screenshot-stream-live.png new file mode 100644 index 0000000..a71338c Binary files /dev/null and b/docs/tutorial/assets/screenshot-stream-live.png differ diff --git a/docs/tutorial/assets/screenshot-stream-search.png b/docs/tutorial/assets/screenshot-stream-search.png new file mode 100644 index 0000000..5243f18 Binary files /dev/null and b/docs/tutorial/assets/screenshot-stream-search.png differ diff --git a/docs/tutorial/assets/screenshot-syscalls.png b/docs/tutorial/assets/screenshot-syscalls.png new file mode 100644 index 0000000..7a63ce3 Binary files /dev/null and b/docs/tutorial/assets/screenshot-syscalls.png differ diff --git a/docs/tutorial/assets/screenshot-tidpicker.png b/docs/tutorial/assets/screenshot-tidpicker.png new file mode 100644 index 0000000..baf08c7 Binary files /dev/null and b/docs/tutorial/assets/screenshot-tidpicker.png differ diff --git a/docs/tutorial/scripts/run-tape.sh b/docs/tutorial/scripts/run-tape.sh new file mode 100755 index 0000000..c22e2e3 --- /dev/null +++ b/docs/tutorial/scripts/run-tape.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# One-tape wrapper: starts the background workload, runs vhs , kills the +# workload. Tapes themselves don't need to know about the workload — they just +# launch ior and drive the TUI. +# +# vhs is invoked with cwd set to the repo root, so all paths inside tapes +# (Output, Screenshot, the ./ior binary) are repo-relative. +# +# Usage: run-tape.sh + +set -euo pipefail + +if [ $# -ne 1 ]; then + echo "usage: $0 " >&2 + exit 2 +fi + +TAPE="$(realpath "$1")" +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +WORKLOAD="${ROOT}/demo/scripts/workload.sh" + +if [ ! -f "$TAPE" ]; then + echo "tape not found: $TAPE" >&2 + exit 2 +fi + +# Pre-flight: vhs and ttyd must be on PATH; sudo timestamp must be live. +command -v vhs >/dev/null || { echo "vhs not on PATH (run: mage installDemoTools)" >&2; exit 3; } +command -v ttyd >/dev/null || { echo "ttyd not on PATH (run: mage installDemoTools)" >&2; exit 3; } +sudo -n true 2>/dev/null || { echo "sudo timestamp expired (run: sudo -v)" >&2; exit 4; } + +# Start workload in its own session/process group so we can kill the whole tree. +setsid "$WORKLOAD" /dev/null 2>&1 & +WL_PID=$! + +cleanup() { + if kill -0 "$WL_PID" 2>/dev/null; then + # The workload runs `setsid` so its PID == its PGID. + kill -TERM -- "-$WL_PID" 2>/dev/null || true + sleep 0.5 + kill -KILL -- "-$WL_PID" 2>/dev/null || true + fi + # Best-effort: stop any straggling ior processes from this tape. + sudo -n pkill -TERM -f '/ior$' 2>/dev/null || true +} +trap cleanup EXIT INT TERM + +# Give the workload a moment to spool up before recording. +sleep 2 + +cd "$ROOT" +vhs "$TAPE" diff --git a/docs/tutorial/scripts/sudo-keepalive.sh b/docs/tutorial/scripts/sudo-keepalive.sh new file mode 100755 index 0000000..4ae1e27 --- /dev/null +++ b/docs/tutorial/scripts/sudo-keepalive.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Refreshes the sudo timestamp every minute so a long demo regen never trips a +# password prompt. Intended to be backgrounded by `mage demo` and killed at the +# end of the run. + +set -u + +trap 'exit 0' TERM INT + +while true; do + sudo -n true 2>/dev/null || exit 1 + sleep 60 +done diff --git a/docs/tutorial/scripts/workload.sh b/docs/tutorial/scripts/workload.sh new file mode 100755 index 0000000..ebbf58b --- /dev/null +++ b/docs/tutorial/scripts/workload.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Background workload for demo tapes. Generates a steady mix of file I/O +# (open/read/close), big writes (fsync/dd), stat-heavy traffic, and ioworkload +# scenarios so every TUI tab has something interesting to display. +# +# Designed to be killed via `kill $!` from the tape wrapper. All children are +# placed in this script's process group so a single signal cleans them up. + +set -u + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +IOWORKLOAD="${ROOT}/../ioworkload" +SCRATCH="$(mktemp -d -t ior-demo-workload-XXXXXX)" +trap 'rm -rf "$SCRATCH"' EXIT + +cleanup() { + trap - TERM INT + # Kill the entire process group so all background loops stop. + kill -- -$$ 2>/dev/null || true + exit 0 +} +trap cleanup TERM INT + +# A) walk /usr and read first byte of each file: tons of openat/read/close + varied paths. +( + while true; do + find /usr/share /usr/lib -maxdepth 4 -type f 2>/dev/null \ + | shuf -n 800 \ + | xargs -r -I{} sh -c 'head -c 1 "{}" >/dev/null 2>&1' || true + sleep 1 + done +) & + +# B) periodic large write with fsync via dd: fills the latency tab with slow writes. +( + while true; do + dd if=/dev/zero of="${SCRATCH}/big.bin" bs=1M count=20 conv=fsync status=none 2>/dev/null || true + sleep 3 + rm -f "${SCRATCH}/big.bin" + done +) & + +# C) stat-heavy directory crawl: feeds the syscall tab with newfstatat/getdents. +( + while true; do + find /etc /var/log -maxdepth 3 >/dev/null 2>&1 || true + sleep 2 + done +) & + +# D) ioworkload scenario rotation if the binary exists: gives us syscall variety +# beyond what the shell utilities trigger (mmap, dup, fcntl, sync, rename, link). +if [ -x "$IOWORKLOAD" ]; then + ( + scenarios=( + open-basic + readwrite-basic + stat-basic + stat-statx + mmap-basic + sync-basic + dup-basic + fcntl-dupfd + rename-basic + link-basic + dir-basic + ) + while true; do + for s in "${scenarios[@]}"; do + "$IOWORKLOAD" --scenario="$s" >/dev/null 2>&1 || true + done + done + ) & +fi + +# Idle until killed. +wait diff --git a/docs/tutorial/tapes/01-launch.tape b/docs/tutorial/tapes/01-launch.tape new file mode 100644 index 0000000..1e2b558 --- /dev/null +++ b/docs/tutorial/tapes/01-launch.tape @@ -0,0 +1,23 @@ +# 01-launch: cold start of ior. Shows the PID picker, then the default landing tab +# (Flamegraph) once Enter selects "All PIDs". +Output demo/assets/01-launch.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 4500ms +Screenshot demo/assets/screenshot-pidpicker.png +Sleep 1500ms +Enter +Sleep 5s +Screenshot demo/assets/screenshot-dashboard.png +Sleep 2s +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/02-overview-tab.tape b/docs/tutorial/tapes/02-overview-tab.tape new file mode 100644 index 0000000..a16a0b8 --- /dev/null +++ b/docs/tutorial/tapes/02-overview-tab.tape @@ -0,0 +1,23 @@ +# 02-overview-tab: dashboard Overview tab — sparkline, top syscalls, top paths fill in. +# Key 2 switches to Overview (key 1 is Flamegraph, the default landing tab). +Output demo/assets/02-overview-tab.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "2" +Sleep 6s +Screenshot demo/assets/screenshot-overview.png +Sleep 1s +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/03-syscalls-tab.tape b/docs/tutorial/tapes/03-syscalls-tab.tape new file mode 100644 index 0000000..376f632 --- /dev/null +++ b/docs/tutorial/tapes/03-syscalls-tab.tape @@ -0,0 +1,36 @@ +# 03-syscalls-tab: sortable syscalls table, j/k to scroll, s/S to sort/reverse-sort. +# Key 3 switches to Syscalls. +Output demo/assets/03-syscalls-tab.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "3" +Sleep 3s +Type "j" +Sleep 400ms +Type "j" +Sleep 400ms +Type "j" +Sleep 800ms +Type "k" +Sleep 600ms +Right +Sleep 600ms +Type "s" +Sleep 1500ms +Type "S" +Sleep 2s +Screenshot demo/assets/screenshot-syscalls.png +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/04-files-tab.tape b/docs/tutorial/tapes/04-files-tab.tape new file mode 100644 index 0000000..49adfee --- /dev/null +++ b/docs/tutorial/tapes/04-files-tab.tape @@ -0,0 +1,32 @@ +# 04-files-tab: files tab plus directory-grouped view toggle (`d`). +# Key 4 switches to Files. +Output demo/assets/04-files-tab.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "4" +Sleep 3s +Type "j" +Sleep 400ms +Type "j" +Sleep 400ms +Type "j" +Sleep 800ms +Type "d" +Sleep 3s +Screenshot demo/assets/screenshot-files-grouped.png +Type "d" +Sleep 2s +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/05-processes-tab.tape b/docs/tutorial/tapes/05-processes-tab.tape new file mode 100644 index 0000000..ad5f64e --- /dev/null +++ b/docs/tutorial/tapes/05-processes-tab.tape @@ -0,0 +1,30 @@ +# 05-processes-tab: processes tab, scroll, and reverse-sort. +# Key 5 switches to Processes. +Output demo/assets/05-processes-tab.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "5" +Sleep 3s +Type "j" +Sleep 400ms +Type "j" +Sleep 400ms +Type "j" +Sleep 800ms +Type "S" +Sleep 2s +Screenshot demo/assets/screenshot-processes.png +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/06-latency-gaps-tab.tape b/docs/tutorial/tapes/06-latency-gaps-tab.tape new file mode 100644 index 0000000..b19ae58 --- /dev/null +++ b/docs/tutorial/tapes/06-latency-gaps-tab.tape @@ -0,0 +1,22 @@ +# 06-latency-gaps-tab: latency + inter-syscall gap histograms (driven by dd writes). +# Key 6 switches to Latency. +Output demo/assets/06-latency-gaps-tab.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "6" +Sleep 8s +Screenshot demo/assets/screenshot-latency.png +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/07-stream-live.tape b/docs/tutorial/tapes/07-stream-live.tape new file mode 100644 index 0000000..9d7ad4f --- /dev/null +++ b/docs/tutorial/tapes/07-stream-live.tape @@ -0,0 +1,22 @@ +# 07-stream-live: stream tab live-tailing rows. +# Key 7 switches to Stream. +Output demo/assets/07-stream-live.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "7" +Sleep 6s +Screenshot demo/assets/screenshot-stream-live.png +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/08-stream-pause-filter.tape b/docs/tutorial/tapes/08-stream-pause-filter.tape new file mode 100644 index 0000000..416830c --- /dev/null +++ b/docs/tutorial/tapes/08-stream-pause-filter.tape @@ -0,0 +1,46 @@ +# 08-stream-pause-filter: pause stream, navigate cells, push two filters onto the stack, undo with Esc. +# Key 7 switches to Stream. +Output demo/assets/08-stream-pause-filter.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "7" +Sleep 4s +Space +Sleep 1s +Down +Sleep 300ms +Down +Sleep 300ms +Down +Sleep 800ms +Right +Sleep 500ms +Right +Sleep 500ms +Enter +Sleep 1500ms +Down +Sleep 400ms +Right +Sleep 400ms +Enter +Sleep 2s +Screenshot demo/assets/screenshot-stream-filtered.png +Escape +Sleep 1s +Escape +Sleep 1500ms +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/09-stream-regex-search.tape b/docs/tutorial/tapes/09-stream-regex-search.tape new file mode 100644 index 0000000..b643740 --- /dev/null +++ b/docs/tutorial/tapes/09-stream-regex-search.tape @@ -0,0 +1,40 @@ +# 09-stream-regex-search: regex search forward (/), n to advance, ? for backward. +# Key 7 switches to Stream. +Output demo/assets/09-stream-regex-search.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "7" +Sleep 4s +Space +Sleep 1s +Type "/" +Sleep 600ms +Type "openat" +Sleep 700ms +Enter +Sleep 1500ms +Type "n" +Sleep 800ms +Type "n" +Sleep 800ms +Screenshot demo/assets/screenshot-stream-search.png +Type "?" +Sleep 600ms +Type "stat" +Sleep 700ms +Enter +Sleep 1500ms +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/10-stream-csv-export.tape b/docs/tutorial/tapes/10-stream-csv-export.tape new file mode 100644 index 0000000..c1f4935 --- /dev/null +++ b/docs/tutorial/tapes/10-stream-csv-export.tape @@ -0,0 +1,28 @@ +# 10-stream-csv-export: 'e' to export current filtered stream snapshot, then ls the CSV produced. +# Key 7 switches to Stream. +Output demo/assets/10-stream-csv-export.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "7" +Sleep 4s +Type "e" +Sleep 2s +Screenshot demo/assets/screenshot-stream-export.png +Sleep 1s +Type "q" +Sleep 1s +Type "ls -lh ior-stream-*.csv" +Enter +Sleep 2s diff --git a/docs/tutorial/tapes/11-pid-tid-probe.tape b/docs/tutorial/tapes/11-pid-tid-probe.tape new file mode 100644 index 0000000..caccc48 --- /dev/null +++ b/docs/tutorial/tapes/11-pid-tid-probe.tape @@ -0,0 +1,41 @@ +# 11-pid-tid-probe: re-open PID picker (p), TID picker (t), probe toggle dialog (o). +Output demo/assets/11-pid-tid-probe.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "p" +Sleep 2s +Down +Sleep 400ms +Down +Sleep 400ms +Screenshot demo/assets/screenshot-pidpicker-open.png +Escape +Sleep 1s +Type "t" +Sleep 2s +Screenshot demo/assets/screenshot-tidpicker.png +Escape +Sleep 1s +Type "o" +Sleep 2s +Down +Sleep 400ms +Down +Sleep 400ms +Screenshot demo/assets/screenshot-probes.png +Escape +Sleep 1s +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/12-parquet-recording.tape b/docs/tutorial/tapes/12-parquet-recording.tape new file mode 100644 index 0000000..c6f3399 --- /dev/null +++ b/docs/tutorial/tapes/12-parquet-recording.tape @@ -0,0 +1,28 @@ +# 12-parquet-recording: start parquet recording (R), accept default filename (Enter), dwell, stop (R), exit, ls the file. +Output demo/assets/12-parquet-recording.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior" +Enter +Sleep 5s +Enter +Sleep 4s +Type "R" +Sleep 1500ms +Enter +Sleep 4s +Screenshot demo/assets/screenshot-recording-active.png +Type "R" +Sleep 1500ms +Type "q" +Sleep 1s +Type "ls -lh ior-recording-*.parquet" +Enter +Sleep 2s diff --git a/docs/tutorial/tapes/13-tui-flamegraph.tape b/docs/tutorial/tapes/13-tui-flamegraph.tape new file mode 100644 index 0000000..7572159 --- /dev/null +++ b/docs/tutorial/tapes/13-tui-flamegraph.tape @@ -0,0 +1,22 @@ +# 13-tui-flamegraph: in-TUI flamegraph view. The default landing tab (key `1`) is the +# live flamegraph. Workload running in the background drives real frame data. +# `-fields` and `-count` let you reshape stack ordering and the size metric. +Output demo/assets/13-tui-flamegraph.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "sudo -n /home/paul/git/ior/ior -fields comm,path,tracepoint -count count" +Enter +Sleep 5s +Enter +Sleep 8s +Screenshot demo/assets/screenshot-flamegraph.png +Sleep 2s +Type "q" +Sleep 1s diff --git a/docs/tutorial/tapes/14-headless-modes.tape b/docs/tutorial/tapes/14-headless-modes.tape new file mode 100644 index 0000000..ce894f6 --- /dev/null +++ b/docs/tutorial/tapes/14-headless-modes.tape @@ -0,0 +1,38 @@ +# 14-headless-modes: all three headless flows in one tape — -flamegraph -name (.ior.zst), +# -parquet (streaming rows), -plain (CSV to stdout). Each capped with -duration so the demo terminates. +Output demo/assets/14-headless-modes.gif +Set Shell "bash" +Set Padding 20 + +Hide +Type "cd $(mktemp -d -t ior-demo-XXXX) && clear" +Enter +Sleep 300ms +Show + +Type "# 1) Aggregated native trace artifact (.ior.zst)" +Enter +Sleep 800ms +Type "sudo -n /home/paul/git/ior/ior -flamegraph -name demo-trace -duration 5" +Enter +Sleep 7s +Type "ls -lh demo-trace*.ior.zst" +Enter +Sleep 2s + +Type "# 2) Per-row streaming Parquet" +Enter +Sleep 800ms +Type "sudo -n /home/paul/git/ior/ior -parquet demo.parquet -duration 5" +Enter +Sleep 7s +Type "ls -lh demo.parquet" +Enter +Sleep 2s + +Type "# 3) Plain CSV to stdout (head only)" +Enter +Sleep 800ms +Type "sudo -n /home/paul/git/ior/ior -plain -duration 3 2>/dev/null | head -n 8" +Enter +Sleep 6s -- cgit v1.2.3