V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lsk569937453
V2EX  ›  Rust

hyper v1+anyhow 可能导致性能急速下降

  •  
  •   lsk569937453 · 202 天前 · 1610 次点击
    这是一个创建于 202 天前的主题,其中的信息可能已经有所发展或是发生改变。

    出问题的源码

    https://gist.github.com/lsk569937453/b42a8cfce21bd20c5da8737db1f5a1b1

    导致的问题

    加了 anyhow = { version = "1.0.xx"}之后,gateway 的 TPS 从 8w 降到 4w(4 核 8G 的 docker 容器)。

    怎么修复

    anyhow = { version = "1.0.xx", default-features = false }

    怎么避免

    • 项目依赖的 crates 中的 anyhow 必须是非 std 的即 anyhow = { version = "1.0.xx", default-features = false }
    • 项目依赖的 crates 中,如果依赖了 anyhow ,也必须是非 std 得。否则,项目会出现性能下降。比如项目依赖了 log4rs 和 https://github.com/BinChengZhao/delay-timer,由于这两个 crates 依赖了 std 的 anyhow ,因此需要将 log4rs 和 delay-timer 排除掉,否则也会出问题。

    问题原因

    目前不确定是 anyhow 的问题还是 hyper v1 的问题。我用同样的代码在 hyper v0.14.xx 实现了一遍,没有发现问题。所以倾向是 hyper v1 的问题。

    12 条回复    2024-06-22 23:49:45 +08:00
    PTLin
        1
    PTLin  
       202 天前
    虽然不知道你代码具体原因是什么,但是 anyhow 1.0.80 不同 feature backtrack 的速度确实不一样,不开启 std feature 的话用的是 anyhow 自己的实现,开启的话用的是标准库的实现,在 Windows 上好像是标准库的实现比较慢。
    ```rust
    use anyhow::anyhow;
    use std::time::Instant;

    fn main() {
    for _ in 0..20 {
    let now = Instant::now();

    for _ in 0..10000 {
    let _ = anyhow!("asd");
    }

    println!("{:?}", now.elapsed());
    }
    }
    ```
    lsk569937453
        2
    lsk569937453  
    OP
       201 天前
    应该和 anyhow 的版本没什么关系,我换成 anyhow = { version = "1.0.70"}还是有同样的问题。
    PTLin
        3
    PTLin  
       201 天前
    又测试了下,调用层数多点能有十多倍的差距
    https://imgur.com/SVIrrfT
    https://imgur.com/2LDykii
    lsk569937453
        4
    lsk569937453  
    OP
       200 天前
    保险起见,不用 anyhow 这个 crate 了,代码改动还小点。
    PTLin
        5
    PTLin  
       200 天前
    @lsk569937453 我比较好奇题主是什么平台运行的代码
    lsk569937453
        6
    lsk569937453  
    OP
       199 天前
    Hantong
        7
    Hantong  
       123 天前
    测试环境:
    rustc 1.78.0 (9b00956e5 2024-04-29), PTLin 给出的代码

    Linux 平台仍然观察到了明显性能折损, profile.release 下, 使用 =1.0.86 版本的 anyhow 比 =1.0.76 版本的 anyhow 慢了 2 倍有余(default-feature = true 下)... 相当恐怖...

    btw, 个人有个 gRPC server 的项目, 观察到 prost 间接依赖了 anyhow, 只能说但凡涉及 gRPC 的几乎全都会受影响, 毕竟 prost 的影响力蛮大的...

    bbtw, 得 anyhow = { version = "=1.0.70" } 这样才能强制指定版本.
    Hantong
        8
    Hantong  
       123 天前
    对于此问题, 修复方法推荐强制指定 anyhow 版本到 =1.0.76
    RTSmile
        9
    RTSmile  
       114 天前 via iPhone
    @Hantong 这个问题 anyhow 的 issue 里面已经有人讨论了,Rust 语言的开发者也有回应说升级到 nightly 版本可能会有性能提升。不过目前的讨论都是仅限于 Windows 版本的,似乎他们并没有注意到 Linux 的性能问题?
    RTSmile
        10
    RTSmile  
       114 天前 via iPhone
    @Hantong anyhow 那边说是 Rust 默认启用了 std 的 backtrace 导致的问题。
    我建议如果你有简单的例子能说明 Linux 上有明显的性能下降的话最好提一下,好像 anyhow 至今对解决这个问题都无动于衷:(
    RTSmile
        11
    RTSmile  
       114 天前 via iPhone
    anyhow 的 issue 里面有人反馈设置 RUST_LIB_BACKTRACE=0 可以解决这个问题。看起来是 rust 标准库里面的 backtrace 导致的问题。
    Hantong
        12
    Hantong  
       89 天前
    @RTSmile 毕竟是 std 的问题, 修复蛮麻烦的.

    benchmark 一下就能看出来, 我原来还不信的.

    最简单的复现代码, 虽然不够严谨. 严谨点得用 benchmark, 或者上火焰图看看什么情况, 我对为什么慢不感兴趣所以没弄.

    ```rust
    fn main() {
    let mut result = Vec::with_capacity(20);

    for _ in 0..20 {
    let now = Instant::now();

    for _ in 0..10000 {
    let _ = anyhow::anyhow!("test error");
    }

    result.push(now.elapsed().as_nanos());
    }

    let avg = result.iter().sum::<u128>() as f64 / 20f64 / 1000f64;

    println!("avg cost: {}s", avg);
    }
    ```

    反正我现在是遵照一位大佬的建议锁 1.0.76 这最后一个正常的版本, 然后所有依赖 anyhow 的库也基本会对齐依赖版本. 还在观察中, 后天有空看看 nightly 版本下的情况.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4453 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 03:59 · PVG 11:59 · LAX 20:59 · JFK 23:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.