owned this note
owned this note
Published
Linked with GitHub
# Rustでパフォーマンス計測
RustのLT会 Shinjuku.rs #7 @FORCIA
---
# About Me
* @11Takanori
* 仕事
* Kotlin, Rust, Python, Dart
* Microservices
---
# 話すこと
- Rustで作られたツールで計測
- Rustで作られたアプリケーションを計測
---
# Rustで作られたツールで計測
---
# Welle
* REST APIを計測するためのコマンドラインツール
* cargo install welleでインストール
---
```
$ welle http://localhost:8080 --num-requests 10000 --concurrent-requests 10
Total Requests: 10000
Concurrency Count: 10
Total Completed Requests: 10000
Total Errored Requests: 0
Total 5XX Requests: 0
Total Time Taken: 960.743592ms
Avg Time Taken: 96.074µs
Total Time In Flight: 8.855463488s
Avg Time In Flight: 885.546µs
Percentage of the requests served within a certain time:
50%: 588.859µs
66%: 905.839µs
75%: 1.245908ms
80%: 1.554109ms
90%: 2.937985ms
95%: 5.523753ms
99%: 11.714656ms
100%: 13.083938ms
```
---
# Drill
* REST APIを計測するためのコマンドラインツール
* YAMLで記述
* cargo install drillでインストール
---
```yaml=
threads: 4
base: "http://localhost:8080"
iterations: 5
rampup: 2
plan:
- name: index
request:
url: /
```
---
```
$ drill --benchmark benchmark.yml --stats
Threads 4
Iterations 5
Rampup 2
Base URL http://localhost:8080
index http://localhost:8080/ 200 OK 1ms
index http://localhost:8080/ 200 OK 0ms
index http://localhost:8080/ 200 OK 0ms
index http://localhost:8080/ 200 OK 3ms
index http://localhost:8080/ 200 OK 0ms
index http://localhost:8080/ 200 OK 1ms
...
index Total requests 20
index Successful requests 20
index Failed requests 0
index Median time per request 1ms
index Average time per request 1ms
index Sample standard deviation 2ms
Concurrency Level 4
Time taken for tests 0.1 seconds
Total requests 20
Successful requests 20
Failed requests 0
Requests per second 157.01 [#/sec]
Median time per request 1ms
Average time per request 1ms
Sample standard deviation 2ms
```
---
# Rustで作られたアプリケーションを計測
---
# cargo bench
* cargo benchで計測
* nightlyのみ対応
* stableとbetaの場合、[bencher](https://crates.io/crates/bencher)というcrateで似たようなことができる
---
計測対象のコード
```rust=
fn fib(n: u32) -> u32 {
if n <= 1 {
n
} else {
fib(n - 2) + fib(n - 1)
}
}
```
---
```rust=
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[bench]
fn bench_fib(b: &mut Bencher) {
b.iter(|| {
let n = test::black_box(10);
fib(n) // 10をfibに直接渡した場合、計算されない
});
}
}
```
---
```
$ cargo bench
running 1 test
test tests::bench_fib ... bench: 287 ns/iter (+/- 25)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out
```
---
# flame
* Cargo.tomlのdependenciesにflameを追加
* 計測したい箇所のコードを修正する必要がある
---
```ruby=
fn main() {
flame::start("read file");
let _x = read_a_file(); // 処理に100msかかる
flame::end("read file");
let _y = flame::span_of("database query", || query_database()); // 処理に200msかかる
let _z = {
let _guard = flame::start_guard("cpu-heavy calculation");
cpu_heavy_operations_1(); // 処理に300msかかる
flame::note("something interesting happened", None);
cpu_heavy_operations_2(); // 処理に100msかかる
};
flame::dump_json(&mut File::create("flame.json").unwrap()).unwrap();
}
```
---
```json=
$ jq . flame.json
[
{
"id": 139687886300416,
"name": "main",
"spans": [
{
"name": "read file",
"start_ns": 6641,
"end_ns": 100083792,
"delta": 100077151,
"depth": 0,
"children": [],
"notes": []
},
{
"name": "database query",
"start_ns": 100087006,
"end_ns": 300203617,
"delta": 200116611,
"depth": 0,
"children": [],
"notes": []
},
{
"name": "cpu-heavy calculation",
"start_ns": 300211351,
"end_ns": 700414510,
"delta": 400203159,
"depth": 0,
"children": [],
"notes": [
{
"name": "something interesting happened",
"description": null,
"instant": 600323628
}
]
}
]
}
]
```
---
# まとめ
* Rustで作られた計測ツールがいくつかある
* コードを修正すれば、内部の処理の計測も簡単
---
# おまけ
---
# flamegraph
* cargo install flamegraph
* perfを外部プロセスとして実行するのでperfのインストールが必要
* Ubuntu18.04なら `sudo apt install linux-tools-4.15.0-66-generic`
* CPUの処理時間を計測
* コードの修正不要
---
下の内容をCargo.tomlに書いてcargo flamegraphを実行すれば、flamegraph.svgが生成される
```toml
[profile.release]
debug = true
```
---
![](https://i.imgur.com/4e7pZts.png)