Rust中的定时异步函数[已关闭]

8xiog9wr  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(111)

**已关闭。**此问题正在寻求书籍,工具,软件库等的建议。它不符合Stack Overflow guidelines。目前不接受答案。

我们不允许您提问有关书籍、工具、软件库等方面的建议。您可以编辑问题,以便您可以通过事实和引用来回答问题。
14小时前关闭
Improve this question
我想在Rust中对异步函数调用计时。crate tracing_timing似乎不合适,因为它不支持异步函数调用。我想的是,在程序运行结束后,我在运行时使用一个经验有效的解决方案是使用一些代码来提供一些功能,如

if cfg!(feature = "timings") {
        let before = SystemTime::now();
        let result = self.get_data(key).await;
        let after = SystemTime::now();
        println!("|get_data|={:?}", after.duration_since(before));
        result
    } else {
        self.get_data(key).await
    }

它工作得很好,很好。这个特性非常类似于C中的**#ifdef TIMINGS**,计时信息被写入一个日志文件,可以在类似的Python脚本运行后查看。但是这个解决方案是C的直接适应,当然Rust必须有一些更惯用的解决方案。
什么是这样一个惯用的rust解决方案?关于如何跟踪rust代码和识别慢点的信息来源是什么?有许多不同的板条箱,它们的相互作用可能很复杂。

iih3973s

iih3973s1#

有很多方法可以做到这一点,这取决于你使用的框架,也取决于你想计时的内容。

从零开始

如果你想知道调用await和返回之间的时间间隔,就像你的例子一样,你可以很容易地创建一个 Package 器函数来完成这个任务。

pub async fn time_async<F, O>(f: F) -> (O, Duration)
where
    F: Future<Output = O>,
{
    let start = Instant::now();
    let out = f.await;
    let duration = start.elapsed();
    (out, duration)
}

你应该使用Instant来查找持续时间。SystemTime对于知道什么时候发生了什么很有用,但是因为它可以在任何时候向前或向后改变(从你的程序的Angular 来看),所以它不适合查找某件事花了多长时间。
然后你就可以随心所欲地记录了。

pub async fn log_time_async<F, D, O>(f: F, name: D) -> O
where
    F: Future<Output = O>,
    D: Display,
{
    if cfg!(feature = "timings") {
        let (out, duration) = time_async(f).await;
        println!("|{name}|={duration:?}");
        out
    } else {
        f.await
    }
}

生态系统

tracing

我相信简单地使用跟踪的enter方法会给予你上面的行为。但是,我不认为订阅者通常会设置为处理这种重叠的跨度(你可以同时等待函数的多个示例),所以你必须测试它是否适合你的情况。

pub async fn trace_async<F, O>(f: F, span: Span) -> O
where
    F: Future<Output = O>,
{
    let guard = span.enter();
    let out = f.await;
    drop(guard);
    out
}

如果你想知道一个future占用了多少executor时间,换句话说,花了多少时间轮询future,那么你需要一个更复杂的解决方案。幸运的是,tracing有一个方法可以做到这一点:instrument,以及macro

// With the method
pub async fn trace_exec<F, O>(f: F, span: Span) -> O
where
    F: Future<Output = O>,
{
    f.instrument(span).await
}

// Or directly on the function
#[tracing::instrument]
pub async fn something_to_time() {
    something_slow().await;
}

这些事件然后可以由订户解释,订户有很多。

log

对于日志记录,跟踪可以与log通信。有关详细信息,请参阅文档。

tokio

时雄有一个名为console的日志框架,它使用instrument跨度来跟踪活动和空闲时间,但它是特定于执行程序的(tokio),而且相当新。
All the code in playground

相关问题