TokioMiddleTechnical

Как профилировать и отлаживать проблемы производительности в приложении на Tokio с помощью tokio-console?

tokio-console — TUI-профилировщик: добавьте console-subscriber::init() и запустите tokio-console. Он показывает живые задачи, время idle/busy, ресурсы и помогает находить зависшие или busy-poll задачи.

tokio-console — инструмент профилирования Tokio

tokio-console — интерактивный терминальный профилировщик для Tokio-приложений. Он использует tracing subscriber внутри приложения и отображает живые данные о задачах, ресурсах и состоянии планировщика через gRPC.

Установка и настройка

# Установить консоль
cargo install --locked tokio-console
# Cargo.toml
[dependencies]
tokio = { version = "1", features = ["full", "tracing"] }
console-subscriber = "0.3"

[profile.release]
debug = 1 # минимальные символы для трассировки
// main.rs — вызвать до #[tokio::main] или в начале main
fn main() {
    console_subscriber::init(); // инициализирует tracing subscriber

    let rt = tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap();

    rt.block_on(run());
}

async fn run() {
    // ваш код
}

Запуск и подключение

# В одном терминале — запустить приложение
TOKIO_CONSOLE_BIND=127.0.0.1:6669 cargo run

# В другом — открыть консоль
tokio-console
# или явно указать адрес
tokio-console http://127.0.0.1:6669

Что показывает консоль

  • Tasks: список задач с их состоянием (running / idle / scheduled), временем ожидания, числом опросов.
  • Resources: мьютексы, семафоры, каналы — показывает ожидающих и владельца.
  • Busy / idle time: соотношение рабочего и ожидающего времени задачи — аномальный idle указывает на зависание.
  • Poll count: задача с тысячами коротких опросов — кандидат на busy-polling.

Диагностика проблем

// Именуйте задачи для читаемости в консоли
let handle = tokio::task::Builder::new()
    .name("db-fetcher")
    .spawn(async move {
        // ...
    })
    .unwrap();

Дополнительные инструменты

  • TOKIO_WORKER_THREADS=1 — уменьшает параллелизм для воспроизведения гонок.
  • tracing-flame — генерирует flamegraph из tracing span'ов.
  • perf + flamegraph (Linux) — CPU профилирование на уровне системных вызовов.
  • heaptrack / cargo-flamegraph — анализ аллокаций.

Переменные окружения

  • TOKIO_CONSOLE_BIND — адрес gRPC сервера (по умолчанию 127.0.0.1:6669).
  • TOKIO_CONSOLE_RETENTION — время хранения завершённых задач (по умолчанию 60s).
  • RUST_LOG=tokio=trace — включает детальный трейсинг событий рантайма.

Подводные камни

  • Требуется feature "tracing": без features = ["tracing"] в зависимости tokio данные задач не собираются.
  • Overhead в production: console-subscriber добавляет заметные накладные расходы; не включайте в production-бинарник без явной необходимости.
  • Совместимость tracing subscriber: если приложение уже использует tracing_subscriber::fmt, нужно использовать console_subscriber::ConsoleLayer как один из слоёв через .with().
  • Имена задач только через Builder: tokio::spawn не принимает имя — только tokio::task::Builder::new().name("...").spawn(...).
  • gRPC порт занят: при запуске нескольких экземпляров приложения укажите разные TOKIO_CONSOLE_BIND для каждого.
  • Нет исторических данных: консоль показывает только текущее состояние и окно retention; для долгосрочного мониторинга используйте Prometheus + Grafana с tokio-metrics.

Common mistakes

  • Отвечать определением без production-сценария.
  • Не называть runtime boundary, security boundary или failure mode.
  • Игнорировать версию API, observability и тестовую проверку.

What the interviewer is testing

  • Объясняет механизм своими словами и без выдуманных API.
  • Называет реальные риски, диагностику и критерий корректности.
  • Связывает ответ с текущей документацией и миграционными ограничениями.

Sources

Related topics