# goschedviz: watching the Go scheduler live in a terminal

> goschedviz is an MIT-licensed Go program that runs any Go binary with GODEBUG schedtrace enabled, parses the scheduler trace as it is produced, and draws the global run queue, the local run queues, thread counts, idle processors and goroutine counts as a live terminal dashboard. It suits somebody learning how the Go scheduler behaves, and its own documentation says it is an educational tool rather than something to run in production.

**justskiv/goschedviz** — 📊 Terminal-based Go scheduler visualization tool with real-time metrics, charts and insights

- Repository: https://github.com/justskiv/goschedviz
- Stars: 533 · Forks: 16
- Language: Go
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/justskiv-goschedviz

## What it is, and the warning that comes with it

goschedviz is a terminal-based visualization tool for the Go runtime scheduler, and the project says it helps understand Go's scheduler behavior by providing real-time metrics visualization.

The important sentence is the warning that follows the description. The tool is for educational purposes only, it's designed to help understand Go scheduler behavior and should not be used in production environments or critical projects, and it may contain bugs and is not optimized for performance.

That is an unusually clear statement, and it is the right one for this category of tool, because a scheduler visualiser is not a profiler. It works by turning on the runtime's own trace output and rendering it, which means the program under observation is running with a debug facility switched on, and the numbers you see describe a program that is not running the way it would in production.

The tool supports any Go program as monitoring target, which is the design that makes it useful. You point it at a source file, it builds and runs that file with the right environment, and it renders what the runtime reports.

The licence is MIT, the primary language is Go, and the recent releases are v0.0.6, a thread count fix, and v0.0.5, goroutines metrics and enhanced visualization, both on 2025-02-23, and v0.0.4 on 2025-02-19, with the last push to the repository on 2026-06-17. The version numbers tell the story: this is a young tool, and the two most recent releases in a single day are the rhythm of a project that is still finding its shape.

The repository also has a Russian translation of the readme, an openspec/ directory for specification-driven development, a CITATION.cff, and a .codecov.yml alongside the coverage badges.

## Installing it, and the two ways to run it

There are two install routes, and they suit different situations.

From source, you clone and build:

```bash
git clone https://github.com/JustSkiv/goschedviz
cd goschedviz
make build
```

and the binary is created in the bin directory.

Or you install it with the Go toolchain directly:

```bash
go install github.com/JustSkiv/goschedviz/cmd/goschedviz@latest
```

which installs the goschedviz binary in your $GOPATH/bin directory, and you need to make sure that directory is on your PATH.

The Makefile behind the first route is three targets and nothing more. The build target creates the bin directory and runs go build on the cmd/goschedviz package, the clean target removes the bin directory, and the test target runs go test with the verbose flag across the tree.

The go.mod file explains the dependency set, and it is deliberately small. The terminal UI is gizak/termui/v3 at version 3.1.0, which is the library that makes the widgets possible, and the rest is testify for the tests and golang.org/x/sys for the system calls a process supervisor needs. The indirect list has the usual terminal stack underneath it, with termbox-go as the older rendering layer, runewidth for character width, which matters for a UI with mixed-width glyphs, and wordwrap and yaml.v3.

That a tool like this pulls in one UI library and nothing else is a good sign. A scheduler visualiser has no business carrying a dependency tree, and the one it has is a terminal UI with no transitive surprises beyond the terminal rendering libraries it already needed.

## Running it, and what the metrics actually are

The basic invocation takes the program to watch and the trace period:

```bash
goschedviz -target=/path/to/your/program.go -period=1000
```

The -target flag is the path to the Go program to monitor, and the -period flag is the GODEBUG schedtrace period in milliseconds, defaulting to 1000.

That period is the sampling interval of the whole tool, and it is worth understanding what it costs. The runtime prints one trace line per period, and each line is a snapshot of the scheduler state at that moment, so a period of 1000 means a sample every second and a period of 100 means ten samples a second, and the cost of the trace itself rises with the frequency. For a program whose behaviour depends on timing, the sampling rate is part of the experiment.

The metrics on screen are the scheduler's own vocabulary, and the documentation lists them in detail.

The current values table shows the current scheduler state including GOMAXPROCS and the thread count. The local run queue bars visualise the queue length for each P, each processor, which is the per-processor view of work waiting to run. The gauges cover the GRQ, the global run queue length, the active goroutines count, the system threads count and the idle processors count. The history plots come in two forms, a linear scale for precise value tracking and a logarithmic scale for better visualization of large ranges.

The legend is the part that makes the plots readable, because it fixes the colour for each metric: GRQ, the global run queue, is green, LRQ, the sum of the local run queues, is magenta, THR, the OS threads, is red, IDL, the idle processors, is yellow, and GRT, the goroutines, is cyan. A fixed palette matters more than it sounds, because a person watching a moving chart learns to read a colour rather than to read a label.

The controls are minimal, with q or Ctrl+C to exit, and terminal resize is supported, which for a full-screen TUI is a requirement rather than a feature.

## How it works, and the part that needs your code

The mechanism is four steps, and they are listed in the documentation.

The tool runs your Go program with GODEBUG=schedtrace enabled. It parses the scheduler trace output in real time. It collects additional runtime metrics, the goroutine count. And it visualizes all of it using a terminal UI.

The third step is where the tool stops being self-contained, and this is the detail that decides whether the goroutine gauge is useful in your case. To enable goroutines count monitoring, you add the metrics reporter to your own program:

```go
package main

import (
    "time"
    "github.com/JustSkiv/goschedviz/pkg/metrics"
)

func main() {
    // Initialize metrics reporter
    reporter := metrics.NewReporter(time.Second)
    reporter.Start()
    defer reporter.Stop()

    // Your program logic here
    ...
}
```

The reporter automatically exports the goroutines count metrics that will be picked up by goschedviz.

So the tool is two things at once. For any unmodified program it is a passive observer of the scheduler's own trace, which is the majority of the information on screen. For the goroutine count, which the runtime does not include in its trace output in a convenient form, the program has to cooperate, and the cooperation is three lines and an import.

The examples directory shows what that looks like in practice, with a simple example, a netpoller example, a netpoller client and server example, and a thread handoff example. The simple one is the smallest useful demonstration of scheduler behaviour:

```go
package main

import "time"

func main() {
    // Create some scheduler load
    for i := 0; i < 1000; i++ {
        go func() {
            time.Sleep(time.Second)
        }()
    }
    time.Sleep(10 * time.Second)
}
```

A thousand goroutines sleeping for a second is a workload that is almost entirely I/O-bound, and watching the run queues and the idle processor count change is a good first lesson in what the scheduler does with work that is not ready to run.

The project also asks for examples, and the guidance on what makes a good one is specific: heavy computation against I/O workloads, different GOMAXPROCS configurations, network-bound applications, memory-intensive operations, and specific scheduler patterns or edge cases. The contribution guide is described as step-by-step, with a development environment setup, code style guidelines, the types of contributions needed and community guidelines, and the project says that if you are new to open source or Go development this is a good place to start.

## Where goschedviz is the wrong tool

The first limit is the one the project states. It is for educational purposes, it should not be used in production environments or critical projects, it may contain bugs and it is not optimized for performance. A scheduler visualiser that adds a trace facility to the runtime changes the thing it is measuring, and a production service instrumented that way is a production service that is slower and differently scheduled.

The second is the platform. The requirements are Go 1.23 or later, a Unix-like operating system of Linux or macOS, and a terminal with colour support. There is no Windows build listed, which is a reasonable constraint for a tool that spawns a child process and reads its output, and a hard one for anybody whose work happens on Windows.

The third is the scope of the answer. The tool shows you scheduler state, which tells you what the runtime is doing, and it does not tell you why. A run queue that is growing is a symptom, and the cause might be a blocking call, a channel with no receiver, a lock held too long, or simply more work than processors. Reaching the cause means a different tool, a CPU profile, a blocking profile, a trace, or a mutex profile.

The fourth is the goroutine count instrumentation, which requires modifying the program you want to observe. That is a real cost in a codebase you do not own, and it is the kind of instrumentation that has to be removed before the program goes anywhere serious, which is a small maintenance trap in a service.

And the fifth is the maturity. The releases are at 0.0.6, two of them landed on the same day in February 2025, and the last push to the repository was in June 2026. That is a project where the code moves when the author has time, and the documentation itself tells you it may contain bugs. For a learning tool that is an acceptable trade, because a slightly wrong scheduler picture is a small cost, and for anything else the numbers are not to be relied on.

The one thing to note about the maintainer's own framing is that the project asks for a citation if you use it in research or educational materials, and it points to the author's YouTube channel and Telegram channels. It is a teaching tool that comes with teaching around it, and that is the shape of the project rather than a limitation.

## Conclusion

goschedviz is worth having if you are trying to build an intuition for how the Go runtime schedules work, because the scheduler's behaviour is otherwise invisible, the tool turns the raw schedtrace lines into a live picture of where goroutines are queueing, and because the two-panel history plot and the per-processor run queue bars make the difference between a compute-bound and an I/O-bound workload visible in a way a profiler flame graph does not. It is the wrong tool for production, and the project says so. Before you use it, check three things: that you are on a Unix-like system with a colour terminal, since the requirements are Linux or macOS, Go 1.23 or later and colour support, and there is no Windows support listed; that you accept the instrumentation cost, because the tool runs your program with GODEBUG=schedtrace enabled, which makes the runtime print a trace line per scheduling period and therefore slows the program you are measuring; and that you know where the goroutine count comes from, because the runtime metrics are exported by a reporter you add to your own program, so a target you do not modify shows the scheduler numbers but not the goroutine gauge.

## FAQ

### How do I install and run goschedviz?

Clone the repository and run make build, which produces the binary in the bin directory, or run go install github.com/JustSkiv/goschedviz/cmd/goschedviz@latest, which puts it in your GOPATH bin directory. Then run it with goschedviz -target=/path/to/your/program.go, where the -period flag sets the GODEBUG schedtrace period in milliseconds and defaults to 1000.

### What metrics does goschedviz display?

A current values table with GOMAXPROCS and the thread count, per-processor local run queue bars, gauges for the global run queue length, the active goroutines count, the system threads count and the idle processors count, history plots on both a linear and a logarithmic scale, and a colour-coded legend where GRQ is green, LRQ is magenta, THR is red, IDL is yellow and GRT is cyan.

### Why does the goroutine count need changes to my program?

The scheduler trace the tool parses does not carry the goroutine count in a form it can use, so the tool collects that separately through a metrics reporter. You import github.com/JustSkiv/goschedviz/pkg/metrics, create a reporter with metrics.NewReporter(time.Second), start it and defer the stop, and the reporter exports the goroutines count metrics that goschedviz then picks up.

## Sources

- [Issues](https://github.com/justskiv/goschedviz/issues)
- [justskiv/goschedviz on GitHub](https://github.com/justskiv/goschedviz)
- [License: MIT](https://github.com/justskiv/goschedviz/blob/main/LICENSE)
- [README](https://github.com/justskiv/goschedviz/blob/main/README.md)
- [Releases](https://github.com/justskiv/goschedviz/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/justskiv-goschedviz
