Skip to content

Commit

Permalink
Add rewrk-core (#38)
Browse files Browse the repository at this point in the history
* Add rewrk core

* Add tests and public interface

* Update CI

* Update docs

* Add timed variants

* Reformat

* Adjust buffer

* Clippy
  • Loading branch information
ChillFish8 authored Feb 12, 2023
1 parent 9c20f0c commit d811b98
Show file tree
Hide file tree
Showing 24 changed files with 2,212 additions and 97 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
/assets
/.github
31 changes: 23 additions & 8 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@ on:
push:
branches: [ master ]
pull_request:
types: [ opened, synchronize, reopened ]
branches: [ master ]

env:
CARGO_TERM_COLOR: always

jobs:
build:
check:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
rust: [stable]

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: Swatinem/rust-cache@v1
- name: Check all targets
run: cargo check --all --all-targets --all-features

build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
rust: [stable]

steps:
- uses: actions/checkout@v2
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- uses: actions/checkout@v2
- uses: Swatinem/rust-cache@v2
- name: Run doc tests
run: cargo test --all
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ serde_json = "1"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "net", "macros"] }
tokio-native-tls = "0.3"
tower = { version = "0.4", features = ["util"] }

[workspace]
members = [
"rewrk-core"
]
31 changes: 19 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
FROM chillfish8/rust-builder:latest as builder
FROM rust:slim-buster as build

WORKDIR /home/rust/
WORKDIR /code

# Avoid having to install/build all dependencies by copying
# the Cargo files and making a dummy src/main.rs
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl
COPY . /code

# Size optimization
RUN strip target/x86_64-unknown-linux-musl/release/rewrk
RUN apt-get update \
&& apt-get install -y libssl-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*

RUN cargo build --release

# Copy the binary into a new container for a smaller docker image
FROM debian:buster-slim

# Start building the final image
FROM scratch
WORKDIR /etc/rewrk

COPY --from=builder /home/rust/target/x86_64-unknown-linux-musl/release/rewrk .
ENTRYPOINT ["./rewrk"]
USER root
RUN apt-get update \
&& apt-get install -y ca-certificates \
&& rm -rf /var/lib/apt/lists/*

COPY --from=build /code/target/release/rewrk .

ENTRYPOINT ["./rewrk"]
Binary file added assets/rewrk-core.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 0 additions & 77 deletions benchmarks/bench_pyre.py

This file was deleted.

36 changes: 36 additions & 0 deletions rewrk-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "rewrk-core"
version = "0.1.0"
edition = "2021"
description = "HTTP benchmarking as a library made simple."
license = "MIT"
readme = "README.md"
repository = "https://github.com/lnx-search/rewrk"
keywords = ["tokio", "async"]
categories = ["concurrency", "asynchronous"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1"
futures-util = "0.3"
http = "0.2"
pin-project-lite = "0.2"
flume = "0.10.14"
hdrhistogram = "7"
thiserror = "1"
async-trait = "0.1.64"
tracing = "0.1.37"
num_cpus = "1.15.0"

hyper = { version = "0.14", features = ["runtime", "client", "http1", "http2"] }
native-tls = { version = "0.2", features = ["alpn"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "net"] }
tokio-native-tls = "0.3"
tower = { version = "0.4", features = ["util"] }

[dev-dependencies]
axum = "0.6.5"
tracing-subscriber = "0.3.16"

tokio = { version = "1", features = ["full"] }
113 changes: 113 additions & 0 deletions rewrk-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# ReWrk Core
HTTP benchmarking as a library made simple.

ReWrk Core is a easily configurable and extendable framework for benchmarking
HTTP servers providing things like response validation, custom result collectors and
custom request producers.

It measures some of the key metrics like latency, write IO and read IO and provides you
with a way of grouping results together with the concept of `tags`.

```rust
use axum::routing::get;
use axum::Router;
use anyhow::Result;
use http::{Method, Request, Uri};
use hyper::Body;
use rewrk_core::{
Batch,
HttpProtocol,
Producer,
ReWrkBenchmark,
RequestBatch,
Sample,
SampleCollector,
};

static ADDR: &str = "127.0.0.1:8080";

#[tokio::test]
async fn test_basic_benchmark() -> Result<()> {
tracing_subscriber::fmt::try_init()?;

tokio::spawn(run_server());

let uri = Uri::builder()
.scheme("http")
.authority(ADDR)
.path_and_query("/")
.build()?;

let mut benchmarker = ReWrkBenchmark::create(
uri,
1,
HttpProtocol::HTTP1,
BasicProducer::default(),
BasicCollector::default(),
)
.await?;
benchmarker.set_num_workers(1);
benchmarker.run().await;

let mut collector = benchmarker.consume_collector().await;
let sample = collector.samples.remove(0);
assert_eq!(sample.tag(), 0);
assert_eq!(sample.latency().len(), 1);
assert_eq!(sample.read_transfer().len(), 1);
assert_eq!(sample.write_transfer().len(), 1);
}

async fn run_server() {
// build our application with a single route
let app = Router::new().route("/", get(|| async { "Hello, World!" }));

axum::Server::bind(&ADDR.parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}

#[derive(Default, Clone)]
pub struct BasicProducer {
count: usize,
}

#[rewrk_core::async_trait]
impl Producer for BasicProducer {
fn ready(&mut self) {
self.count = 1;
}

async fn create_batch(&mut self) -> Result<RequestBatch> {
if self.count > 0 {
self.count -= 1;

let uri = Uri::builder().path_and_query("/").build()?;
let request = Request::builder()
.method(Method::GET)
.uri(uri)
.body(Body::empty())?;
Ok(RequestBatch::Batch(Batch {
tag: 0,
requests: vec![request],
}))
} else {
Ok(RequestBatch::End)
}
}
}

#[derive(Default)]
pub struct BasicCollector {
samples: Vec<Sample>,
}

#[rewrk_core::async_trait]
impl SampleCollector for BasicCollector {
async fn process_sample(&mut self, sample: Sample) -> Result<()> {
self.samples.push(sample);
Ok(())
}
}
```
Loading

0 comments on commit d811b98

Please sign in to comment.