Read this in other languages: English
gcscope - терминальный TUI-инструмент для наблюдения за работой сборщика мусора Go в реальном времени. Он показывает GC-циклы, STW-паузы, динамику динамику кучи (live/goal) и сигналы GC pacer прямо в терминале.
Источники данных: gctrace, gcpacertrace и runtime/metrics (режимы run и attach).
Типичные сценарии, где он помогает:
- заметить всплески STW-пауз под нагрузкой
- увидеть, стал ли GC срабатывать чаще или реже после изменений в коде
- понять, как heap live приближается к heap goal и когда pacing становится агрессивнее
- сравнить два запуска по snapshot-файлам (
diff)
- Как устроено
- Установка
- Быстрый старт (1 минута)
- Режимы и команды
- Что показывает UI (метрики и панели)
- Хоткеи
- Настройки
- Snapshots
- Makefile: список команд и зачем они нужны
- Notes / FAQ
- Разработка
- Лицензия
У gcscope есть два источника данных:
run— основной режим: запускает ваш бинарник, добавляет вGODEBUGзначенияgctrace=1,gcpacertrace=1и разбираетstderrцелевого процесса.attach— дополнительный режим: опрашивает HTTP-эндпоинт, который отдаётruntime/metricsв JSON-формате, понятномgcscopeчерезpkg/reporter.
Для режима run менять код приложения не нужно. Для режима attach нужно добавить в сервис небольшой HTTP-эндпоинт.
Выберите один из вариантов ниже.
Установить gcscope в GOBIN:
go install github.com/timur-developer/gcscope/cmd/gcscope@latestПосле этого можно запускать как обычную команду (из любой папки):
gcscope lab churn
gcscope run ./path/to/your-binary -- --your-flag value
gcscope attach http://127.0.0.1:8080/gcscope/metrics
gcscope diff ./a.json ./b.jsonВстроенная справка:
gcscope --help
gcscope run --helpСкачайте готовый бинарник со страницы GitHub Releases (Assets), выберите архив под вашу OS/arch и распакуйте.
Запуск из распакованной папки:
Windows (PowerShell):
.\gcscope.exe lab churnmacOS / Linux:
chmod +x ./gcscope
./gcscope lab churnЧтобы запускать gcscope из любой папки, переместите бинарник в директорию из PATH (или добавьте папку с бинарником в PATH).
go run ./cmd/gcscope lab churnТребования: Go 1.22+ и достаточно большое окно терминала.
Из исходников (без установки):
go run ./cmd/gcscope lab churnИли через Makefile:
make lab-churnСправка внутри приложения доступна по ? / h / f1.
- Соберите ваше приложение в бинарник:
go build -o ./myapp ./cmd/myapp- Запустите под наблюдением:
go run ./cmd/gcscope run ./myapp -- --your-flag valueРазделитель -- нужен, чтобы отделить аргументы gcscope от аргументов вашей программы.
- В UI:
?- открыть справку со всеми хоткеямиspace- пауза/продолжить- в паузе
left/right(иhome/end) листают историю sсохраняет snapshot-файл вtmp/snapshots(по умолчанию)
Если хотите использовать gcscope как обычный CLI (однажды установить и дальше запускать gcscope ...), см. раздел Установка.
Запускает ваш бинарник и в реальном времени показывает события GC:
gcscope run ./path/to/your-binaryЭтот режим предназначен для того, чтобы посмотреть, как сборщик мусора Go ведет себя именно в вашем проекте во время реального запуска.
run работает с уже собранным бинарником (а не с .go файлом), поэтому сначала соберите приложение, а затем передайте путь к исполняемому файлу в gcscope.
Нужны флаги gcscope или нужно передать аргументы вашей программе? См. раздел Настройки.
Из исходников:
go run ./cmd/gcscope run ./path/to/your-binaryЧерез Makefile:
make run TARGET=./path/to/your-binarylab запускает встроенную нагрузку, чтобы можно было быстро посмотреть работу приложения и разобраться с хоткеями.
gcscope lab alloc
gcscope lab churn
gcscope lab idle
gcscope lab spikeЧто примерно означает каждый пресет:
alloc: ровные небольшие/средние аллокации с частичным удержанием (heap live плавно растет, GC срабатывает стабильно)churn: повторяющиеся крупные всплески с коротким удержанием (частые GC, удобно смотреть STW/pacer под нагрузкой)idle: почти бездействие, но иногда небольшие всплески (редкие GC-события, поведение при низкой активности)spike: лёгкая фоновая нагрузка и периодические тяжёлые всплески (хорошо видно скачки в heap/STW показателях)
Подключение к уже работающему сервису, который отдает runtime/metrics в JSON-формате gcscope.
- Добавьте
pkg/reporterв сервис:
package main
import (
"log"
"net/http"
"github.com/timur-developer/gcscope/pkg/reporter"
)
func main() {
rep := reporter.New()
mux := http.NewServeMux()
mux.Handle(rep.Path(), rep.Handler())
log.Fatal(http.ListenAndServe(":8080", mux))
}- Подключитесь:
gcscope attach http://127.0.0.1:8080/gcscope/metricsВажные нюансы attach режима:
- данные берутся из
runtime/metrics, поэтому они отличаются отrunрежима - env переменные (
GOGC,GOMEMLIMIT,GODEBUG) недоступны, UI покажетn/a
Сравнение двух snapshot-файлов:
gcscope diff ./a.json ./b.jsonЧто выводит diff:
- краткую сводку по snapshot A и B (
gc_cycles_total,heap_live_mb,stw_p50/p99/max_us) - разницу (B-A) для
heap_live_mbи STW метрик окна
gcscope хранит скользящее окно последних GC событий (--window-size, по умолчанию: 200) и показывает как значения по циклам, так и агрегаты по окну.
GC cycles total: текущий номер GC циклаlast STW (us): STW пауза последнего цикла (sweep term + mark term, в микросекундах)heap live (MB)/heap goal (MB): live heap и целевой размер кучиheap: live/goal: компактный индикатор соотношения live/goal
max STW (us): максимальная STW-пауза в текущем окнеgc: частота GC вGCs/minи/или средний интервал между GCstw: количество и процент «плохих» STW-пауз по заданным порогам, а также количество forced GCtime since last GC,uptimestw thresholds: порогиwarn/bad(см. настройки)- состояние snapshot и директория snapshot
- контекст env-окружения (
GOGC,GOMEMLIMIT,GODEBUG) вrun/lab(вattachнедоступен)
- Heap live over time (MB): heap live во времени
- STW p50/p99/max over time (us): p50/p99/max STW по окну
- STW per cycle: bar chart по циклам; подписи можно переключать на STW или heap live (
l)
- GC #, time since start, forced
- STW total (us) + разбивка: sweep term / mark term (фазы GC)
- heap (MB): start/end и live/goal
- gc cpu (%)
- pacer сигналы (если доступны): assist ratio, assist workers, pages swept
Полный список горячих клавиш всегда доступен в Help (? / h / f1).
База:
?/h/f1показать/скрыть Helpq/ctrl+cвыходspaceпауза/продолжить обновленияleft/rightлистать историю (в паузе)home/endв начало/конец истории (в паузе)sсохранить snapshot
Интерфейс:
gпереключить layout (spaced/tight)lрежим подписей STW bar chart (GC+STW -> GC+Heap -> GC-only)
Графики:
zвыбрать активный график (Heap/STW). Zoom/pan применяется к активному графику.+/-Y-zoom активного графика0сброс Y zoom/pan активного графикаshift+up/shift+downY-pan активного графика[/]X-zoom (масштаб по времени): all -> 1h -> 15m -> 5m -> 1m (и обратно)rполный сброс focus, zoom/pan и time span
Глобальные флаги (и env-оверрайды):
--window-size(GCSCOPE_WINDOW_SIZE) количество событий в памяти (default: 200)--snapshot-path(GCSCOPE_SNAPSHOT_PATH) директория snapshots (default:tmp/snapshots)--exit-snapshot(GCSCOPE_EXIT_SNAPSHOT) snapshot на выходе (default: true)--no-alt-screen(GCSCOPE_NO_ALT_SCREEN) отключить alt screen buffer--stw-warn-us(GCSCOPE_STW_WARN_US) порог warn для STW (default: 200)--stw-bad-us(GCSCOPE_STW_BAD_US) порог bad для STW (default: 1000)
Режимные env:
GCSCOPE_RUN_TARGETGCSCOPE_ATTACH_URL,GCSCOPE_POLL_INTERVALGCSCOPE_LAB_PRESETGCSCOPE_DIFF_A,GCSCOPE_DIFF_B
Любой флаг можно задавать и через соответствующую переменную окружения GCSCOPE_*, перечисленную выше.
Глобальные флаги (например, --window-size, --stw-bad-us) пишутся до подкоманды, потому что они относятся ко всем режимам.
В режиме run разделитель -- отделяет аргументы gcscope от аргументов вашей программы. Все, что после --, передается вашему бинарнику как есть.
Шаблон:
gcscope [глобальные флаги] run <target-binary> -- [аргументы вашей программы...]Пример:
gcscope --window-size 500 --stw-bad-us 2000 run ./path/to/your-binary -- --your-flag valueSnapshot - это JSON-файл, который фиксирует состояние "последних N GC-событий" (то же окно, которое использует UI). Его удобно сохранять для сравнения запусков, обмена и фиксации регрессий.
По умолчанию snapshot-файлы пишутся в tmp/snapshots.
- ручной snapshot:
s - snapshot при выходе включен по умолчанию; пропускается, если в течение 5 секунд перед выходом snapshot был сделан вручную
Что внутри snapshot:
- текущие значения (
gc_cycles_total,last_stw_us,heap_live_mb,heap_goal_mb) - агрегаты окна (
stw_p50_us,stw_p99_us,stw_max_us) - список событий GC в окне (включая распарсенные pacer-поля, если они были доступны)
make help выводит список целей. Основные:
make ci: прогоняет линтер, тесты и сборкуmake lint: запускаетgolangci-lintmake test: запускаетgo test ./...make build:go build ./...(быстрая проверка, что все собирается)make install: устанавливаетgcscopeв вашу Go bin директориюmake lab/make lab-churnи т.п.: запускает демо-нагрузкиmake run TARGET=... ARGS="-- ...": запускает ваш бинарник под наблюдениемmake attach URL=...: подключается к сервису (по умолчаниюhttp://127.0.0.1:8080/gcscope/metrics)make diff A=... B=...: сравнивает два snapshot-файла
Для мейнтейнеров:
make testbin: пересобирает встроенныеlab-бинарники под все поддерживаемые OS/archmake release-snapshot: локальная сборка релиза через GoReleaser (--snapshot --clean)
- В
attachрежиме нельзя узнать env параметры (GOGC,GOMEMLIMIT,GODEBUG), поэтому UI показываетn/a. - Если вы не видите обновлений, возможно, приложение пока не вызывало сборщик мусора (подождите, пока runtime его вызовет).
- Если терминал ведет себя странно, попробуйте
--no-alt-screen(илиGCSCOPE_NO_ALT_SCREEN=true). - Очень маленькие STW значения могут отображаться как 0 из-за форматирования
gctrace.
make ci
make lint
make test
make buildMIT. См. LICENSE.



