Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The thing you would otherwise reach for is `perf record` followed by `perf repor
## Questions this tool answers

**One process is pinning a core and I need to know which function, right now.**
`yeet run . --tty`, click the process, and read the top of the table. Rows are self-time only, sorted hottest first, so the top row is where the CPU actually is rather than a caller that merely contains it. The first rows land in about a second at the default 499 Hz. See [What you're looking at](#what-youre-looking-at).
`yeet run gh:yeet-src/hotspot --tty`, click the process, and read the top of the table. Rows are self-time only, sorted hottest first, so the top row is where the CPU actually is rather than a caller that merely contains it. The first rows land in about a second at the default 499 Hz. See [What you're looking at](#what-youre-looking-at).

**I'm SSHed into a box where I can't install `perf` and there's no matching `linux-tools` package. Can I still profile?**
Yes, and this is the case the shape is for. `perf` needs a `linux-tools` build matched to the running kernel, which is exactly what a minimal or slightly-behind image doesn't have. `hotspot` needs the yeet daemon and this script; the sampler is a CO-RE BPF program, so there's no per-kernel recompile and nothing to match. It draws in the terminal you're already in, so there's also no port to forward.
Expand Down Expand Up @@ -72,11 +72,23 @@ Not directly. `hotspot` is a mouse-driven TUI with no headless mode and no `--js
## Quick start

```sh
curl -fsSL https://yeet.cx | sh
curl -fsSL https://yeet.cx | sh # install yeet, once
yeet run gh:yeet-src/hotspot --tty # clone, build and run in one step
```
[Manual install guide](https://yeet.cx/docs/install/manual-installation?utm_source=github&utm_medium=readme&utm_campaign=hotspot) | Linux only

That is the whole install. `yeet run` clones the repo into its own cache, runs `make` to
compile `bin/probe.bpf.o` and bundle the JS, then starts the script; the BPF toolchain is
fetched automatically, so there is no clang, bpftool or `linux-tools` to install first.
`yeet-src` is a trusted source for the runtime, so the build runs without a consent prompt.

Working on the script itself instead of just running it? Clone it and build in place:

```sh
git clone https://github.com/yeet-src/hotspot && cd hotspot
make # compile bin/probe.bpf.o + bundle the JS (toolchain auto-fetched)
yeet run . --tty # the live process table; click a process to profile it
```
[Manual install guide](https://yeet.cx/docs/install/manual-installation?utm_source=github&utm_medium=readme&utm_campaign=hotspot) | Linux only

With no flags you land on the process table: every process with an executable, sorted by name. Kernel threads are filtered out because they have no `exe` and no user stacks. Click a row to select it, click the selected row (or `⏎`) to start profiling, and the pane becomes a live profile. No sampling happens until you open a process.

Expand All @@ -90,11 +102,14 @@ Script flags go **after `--`** so the runtime routes them to the script rather t
| `--strip=<prefix>` | none | strip a build-machine path prefix from DWARF paths to make them repo-relative |

```sh
yeet run . --tty -- --freq 997 # sample harder
yeet run . --tty -- --repo torvalds/linux --rev v6.12 # link kernel rows to a tag
yeet run . --tty -- --repo me/svc --strip /build/src/ # bridge a container build path
R=gh:yeet-src/hotspot
yeet run $R --tty -- --freq 997 # sample harder
yeet run $R --tty -- --repo torvalds/linux --rev v6.12 # link kernel rows to a tag
yeet run $R --tty -- --repo me/svc --strip /build/src/ # bridge a container build path
```

(From a clone, `.` replaces `gh:yeet-src/hotspot` in any of these.)

Runs until `q` or `Ctrl-C`. Resize the terminal and every view reflows. It needs a real terminal and mouse reporting, so don't pipe or redirect it.

## Have an agent set it up
Expand Down Expand Up @@ -302,6 +317,9 @@ The trade is honest: sampling is statistical and cannot tell you a function was

## Building from source

You only need this section if you're changing the script. `yeet run gh:yeet-src/hotspot` runs
`make` for you against its own cached clone.

```sh
make # build bin/probe.bpf.o (clang + bpftool) + bundle the JS (esbuild)
make bpf # just the BPF object
Expand Down Expand Up @@ -370,6 +388,12 @@ There's no capture script; [`demo/README.md`](demo/README.md) has the recording

## FAQ

**`yeet run gh:yeet-src/hotspot` fails with `could not read Username for 'https://github.com'`.**
That is a clone-authentication failure, not a script problem. `gh:` shorthand tries SSH first
(`git@github.com:yeet-src/hotspot`) so private repos work with your own keys, then retries over
HTTPS. If neither has a usable credential you get this. Check `ssh -T git@github.com` succeeds,
or clone it yourself and run `yeet run . --tty` from the directory.

**Why is the top row `??` with a spinner that never resolves?**
A spinner means queued, and a spinner that persists means the batch failed rather than that it's slow. The status line shows `sym: <error>` when symbolization errored; the most common cause is the process exiting while being profiled, since the resolver reads its live maps. Reopen the process.

Expand Down
Loading