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

294 天前
 lsk569937453

出问题的源码

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 }

怎么避免

问题原因

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

1746 次点击
所在节点    Rust
13 条回复
PTLin
294 天前
虽然不知道你代码具体原因是什么,但是 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
294 天前
应该和 anyhow 的版本没什么关系,我换成 anyhow = { version = "1.0.70"}还是有同样的问题。
PTLin
294 天前
又测试了下,调用层数多点能有十多倍的差距
https://imgur.com/SVIrrfT
https://imgur.com/2LDykii
lsk569937453
292 天前
保险起见,不用 anyhow 这个 crate 了,代码改动还小点。
PTLin
292 天前
@lsk569937453 我比较好奇题主是什么平台运行的代码
lsk569937453
292 天前
Hantong
215 天前
测试环境:
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
215 天前
对于此问题, 修复方法推荐强制指定 anyhow 版本到 =1.0.76
RTSmile
207 天前
@Hantong 这个问题 anyhow 的 issue 里面已经有人讨论了,Rust 语言的开发者也有回应说升级到 nightly 版本可能会有性能提升。不过目前的讨论都是仅限于 Windows 版本的,似乎他们并没有注意到 Linux 的性能问题?
RTSmile
207 天前
@Hantong anyhow 那边说是 Rust 默认启用了 std 的 backtrace 导致的问题。
我建议如果你有简单的例子能说明 Linux 上有明显的性能下降的话最好提一下,好像 anyhow 至今对解决这个问题都无动于衷:(
RTSmile
207 天前
anyhow 的 issue 里面有人反馈设置 RUST_LIB_BACKTRACE=0 可以解决这个问题。看起来是 rust 标准库里面的 backtrace 导致的问题。
Hantong
181 天前
@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 版本下的情况.
Hantong
61 天前
目前根据 bench 结果:

```
Gnuplot not found, using plotters backend
Anyhow/anyhow/v1.0.76 time: [46.255 ns 50.158 ns 54.338 ns]
change: [-3.3466% +7.6940% +20.010%] (p = 0.18 > 0.05)
No change in performance detected.
Found 5 outliers among 100 measurements (5.00%)
3 (3.00%) high mild
2 (2.00%) high severe
Anyhow/anyhow/v1.0.90 time: [48.072 ns 56.167 ns 63.721 ns]
change: [-29.746% +34.093% +175.67%] (p = 0.69 > 0.05)
No change in performance detected.
Found 16 outliers among 100 measurements (16.00%)
11 (11.00%) high mild
5 (5.00%) high severe
```

但是我的测试环境发生变动: AMD AI9 HX370, 7500MT LPDDR5.

```
rustc 1.84.0-nightly (e7c0d2750 2024-10-15)
binary: rustc
commit-hash: e7c0d2750726c1f08b1de6956248ec78c4a97af6
commit-date: 2024-10-15
host: x86_64-pc-windows-msvc
release: 1.84.0-nightly
LLVM version: 19.1.1
```

测试代码:

```rust
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};

fn bench_maps(c: &mut Criterion) {
let mut group = c.benchmark_group("Anyhow");

group.bench_function("anyhow/v1.0.76", |b| {
b.iter_batched(
|| anyhow_1_0_76::anyhow!("test error"),
|e| {
criterion::black_box({
let _ = e;
});
},
BatchSize::SmallInput,
)
});

group.bench_function("anyhow/v1.0.90", |b| {
b.iter_batched(
|| anyhow_1_0_90::anyhow!("test error"),
|e| {
criterion::black_box({
let _ = e;
});
},
BatchSize::SmallInput,
)
});
}

criterion_group!(benches, bench_maps);
criterion_main!(benches);
```

切换至当前 stable rust 测试:

```
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-pc-windows-msvc
release: 1.81.0
LLVM version: 18.1.7
```

```
Running benches/anyhow.rs (target\release\deps\anyhow-e035dda9f6eff98f.exe)
Gnuplot not found, using plotters backend
Anyhow/anyhow/v1.0.76 time: [7.3229 ns 7.5644 ns 7.9092 ns]
change: [-5.8063% -1.9072% +1.6252%] (p = 0.33 > 0.05)
No change in performance detected.
Found 7 outliers among 100 measurements (7.00%)
3 (3.00%) high mild
4 (4.00%) high severe
Anyhow/anyhow/v1.0.90 time: [46.830 ns 53.064 ns 59.741 ns]
change: [-16.795% -3.3065% +13.223%] (p = 0.68 > 0.05)
No change in performance detected.
Found 6 outliers among 100 measurements (6.00%)
3 (3.00%) high mild
3 (3.00%) high severe
```

emmm, 奇怪的结果.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1019962

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX