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

2024-03-02 08:54:50 +08:00
 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 的问题。

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