Rust 异步编程与 Tokio 开发短记:卡顿时先查哪里
“卡顿”对我来说先不是一个结论,而是一条观察:某个请求等得比平时久。刚学 Tokio 时,我会先检查 async 函数里有没有同步 I/O、很长的 CPU 循环,或者拿着锁再.await。这三项不一定就是原因,但很适合作为最小排查清单。
下面的函数只是在开发时给一个异步步骤记耗时,不替代完整的性能分析。
use std::future::Future; use std::time::Instant; async fn measure<F, T>(task: F) -> (T, std::time::Duration) where F: Future<Output = T>, { let started = Instant::now(); let output = task.await; (output, started.elapsed()) } #[tokio::test] async fn measures_an_async_step() { let (value, elapsed) = measure(async { 2 + 3 }).await; assert_eq!(value, 5); assert!(elapsed >= std::time::Duration::ZERO); }如果耗时确实异常,我会再把范围缩小:用tracing标出入口和关键 await 点,确认是等待网络、等待锁,还是任务本身在占用 CPU。CPU 密集的工作可能需要spawn_blocking;但它也不是随处可用的补丁,任务量和取消方式都要重新看。
不要预先写一个固定阈值说“超过多少毫秒就是卡顿”。不同的任务预期不同,开发机上的结果也不能当成线上结论。先记录自己的测试条件和现象,再用 profiler 或tokio-console验证猜测,改动后重跑同一个小例子。这比凭感觉扩容 channel 更可靠。