2个版本

0.1.1 2024年3月26日
0.1.0 2024年3月12日

#73性能分析 分类中

Download history 24/week @ 2024-04-07 200/week @ 2024-04-14 144/week @ 2024-04-21 284/week @ 2024-04-28 150/week @ 2024-05-05 128/week @ 2024-05-12 141/week @ 2024-05-19 84/week @ 2024-05-26 88/week @ 2024-06-02 115/week @ 2024-06-09 54/week @ 2024-06-16 28/week @ 2024-06-23 63/week @ 2024-06-30 72/week @ 2024-07-07 44/week @ 2024-07-14 146/week @ 2024-07-21

每月325次下载

Apache-2.0

105KB
2K SLoC

Windsock - 一个数据库基准测试框架

Windsock是一个通用的数据库基准测试框架。

你将做什么

  • 提供你自己的Rust异步兼容数据库驱动程序
  • 定义你的基准逻辑,该逻辑将一些简单的统计信息返回给Windsock
  • 定义你的基准池

Windsock将做什么

  • 提供命令行界面,你可以
    • 查询可用的基准
    • 有选择地运行基准
    • 将基准结果处理成可读的表格

Windsock适合于

  • 在数据库或服务开发过程中迭代测试性能(对于微基准测试,你可能需要不同的工具)
  • 调查你打算使用的数据库上不同工作负载的性能。

定义基准

要使用Windsock,创建一个导入Windsock的Rust crate

windsock = "0.1"

然后像这样实现crate(简化版)

fn main() {
    // Define our benchmarks and give them to windsock
    Windsock::new(vec![
        Box::new(CassandraBench { topology: Topology::Cluster3 }),
        Box::new(CassandraBench { topology: Topology::Single })
    ])
    // Hand control of the app over to windsock
    // Windsock processes CLI args, possibly running benchmarks and then terminates.
    .run();
}

pub struct CassandraBench { topology: Topology }

#[async_trait]
impl Bench for CassandraBench {
    // define tags that windsock will use to filter and name the benchmark instance
    fn tags(&self) -> HashMap<String, String> {
        [
            ("name".to_owned(), "cassandra".to_owned()),
            (
                "topology".to_owned(),
                match &self.topology {
                    Topology::Single => "single".to_owned(),
                    Topology::Cluster3 => "cluster3".to_owned(),
                },
            ),
        ]
        .into_iter()
        .collect()
    }

    // the benchmark logic for this benchmark instance
    async fn run(&self, runtime_seconds: usize, operations_per_second: Option<u64>, reporter: UnboundedSender<Report>) {
        // bring up the DB
        let _handle = init_cassandra();

        // create the DB driver session
        let session = init_session().await;

        // spawn tokio tasks to concurrently hit the database
        // The exact query is defined in `run_one_operation` below
        BenchTaskCassandra { session }.spawn_tasks(reporter.clone(), operations_per_second).await;

        // tell windsock to begin benchmarking
        reporter.send(Report::Start).unwrap();
        let start = Instant::now();

        // run the bench for the time requested by the user on the CLI (defaults to 15s)
        tokio::time::sleep(Duration::from_secs(runtime_seconds)).await;

        // tell windsock to finalize the benchmark
        reporter.send(Report::FinishedIn(start.elapsed())).unwrap();
    }
}

// This struct is cloned once for each tokio task it will be run in.
#[derive(Clone)]
struct BenchTaskCassandra {
    session: Arc<Session>,
}

#[async_trait]
impl BenchTask for BenchTaskCassandra {
    async fn run_one_operation(&self) -> Result<(), String> {
        self.session.query("SELECT * FROM table").await
    }
}

待办事项:记录以独立crate和cargo bench运行Windsock的方法。

此示例简化以供演示,请参阅 examples/cassandra.rs 以获取完整的工作示例。

运行基准

然后我们运行我们的crate以运行基准并查看结果,如下所示

> cargo windsock run-local
... benchmark running logs
> cargo windsock results
Results for cassandra
           topology   ──single ─cluster3
Measurements ═══════════════════════════
   Operations Total     750762    372624
 Operations Per Sec      83418     41403
             Min       0.255ms   0.229ms
               1       0.389ms   0.495ms
               2       0.411ms   0.571ms
               5       0.460ms   0.714ms
              10       0.567ms   0.876ms
              25       1.131ms   1.210ms
              50       1.306ms   1.687ms
              75       1.519ms   2.600ms
              90       1.763ms   4.881ms
              95       2.132ms   7.542ms
              98       2.588ms  14.008ms
              99       2.951ms  19.297ms
              99.9     7.952ms  40.896ms
              99.99   25.559ms  80.692ms

待办事项:将其转换为更炫酷的比较,并使用图片包含着色

如何在Windsock中执行各种任务

运行所有基准

> cargo windsock run-local

运行带有匹配标签的基准,并在一个表格中查看所有结果

> cargo windsock run-local db=kafka OPS=1000 topology=single # run benchmarks matching some tags
> cargo windsock results # view the results of the benchmarks with the same tags in a single table

迭代比较与先前实现的差异

> git checkout main # checkout original implementation
> cargo windsock run-local # run all benchmarks
> cargo windsock baseline-set # set the last benchmark run as the baseline
> vim src/main.rs # modify implementation
> cargo windsock run-local # run all benchmarks, every result is compared against the baseline
> cargo windsock results # view those results in a nice table
> vim src/main.rs # modify implementation again
> cargo windsock run-local # run all benchmarks, every result is compared against the baseline

在云端运行基准(简单)

# create cloud resources, run benchmarks and then cleanup - all in one command
> cargo windsock cloud-setup-run-cleanup

迭代比较与先前实现的差异(在远程云端运行)

# Setup the cloud resources and then form a baseline
> git checkout main # checkout original implementation
> cargo windsock cloud-setup db=kafka # setup the cloud resources required to run all kafka benchmarks
> cargo windsock cloud-run db=kafka # run all the kafka benchmarks in the cloud
> cargo windsock baseline-set # set the last benchmark run as the baseline

# Make a change and and measure the effect
> vim src/main.rs # modify implementation
> cargo windsock cloud-run db=kafka # run all benchmarks, every result is compared against the baseline
> cargo windsock results # view those results in a nice table, compared against the baseline

# And again
> vim src/main.rs # modify implementation again
> cargo windsock cloud-run db=kafka # run all benchmarks, every result is compared against the baseline

# And finally...
> cargo windsock cloud-cleanup # Terminate all the cloud resources now that we are done

生成图形网页

待办事项:计划中,但尚未实现

> cargo windsock local-run # run all benches
> cargo windsock generate-webpage # generate a webpage from the results

依赖关系

~5–15MB
~164K SLoC