Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brotli compression performace #174

Closed
barvirm opened this issue Oct 7, 2022 · 7 comments
Closed

Brotli compression performace #174

barvirm opened this issue Oct 7, 2022 · 7 comments

Comments

@barvirm
Copy link

barvirm commented Oct 7, 2022

Hello, I started to use tower-http compression layer, and I notice a significant slowdown in my server.
After some measurements, I found out that, the Brotli encoder is able to compress my file (300Kb) in 10ms, but after compression, the encoder state is changed to BROTLI_OPERATION_FLUSH which takes 3.5s.

@barvirm
Copy link
Author

barvirm commented Oct 7, 2022

Minimal example:

use async_compression::tokio::bufread::BrotliEncoder;
use tokio::{fs::File, io::{AsyncReadExt, BufReader}};

use std::time::Instant;

#[tokio::main]
async fn main() {
    // File with size: 1,7 MB
    let file = File::open("test.bin").await.unwrap(); 
    let reader = BufReader::new(file);
    let mut buffer = Vec::with_capacity(2_000_000);

    let start = Instant::now();

    let mut encoder = BrotliEncoder::new(reader);
    encoder.read_to_end(& mut buffer).await.unwrap();

    let elapsed = start.elapsed();

    // +/- 20s
    println!("elapsed: {:#?}", elapsed);
}

@Nemo157
Copy link
Member

Nemo157 commented Oct 7, 2022

I did a slight modification to test with random data (and try eliminate any IO times by reading everything at once):

    let file = File::open("/dev/urandom").await.unwrap();
    let reader = BufReader::with_capacity(2_000_000, file.take(1_700_000));

I don't get 20s, but I do see 2.5s in debug mode and 500ms in release which still seems way too long.

@Nemo157
Copy link
Member

Nemo157 commented Oct 7, 2022

Actually, that still doesn't read everything at once, this does:

    let file = File::open("/dev/urandom").await.unwrap();
    let mut bytes = Vec::with_capacity(2_000_000);
    file.take(1_700_000).read_to_end(&mut bytes).await.unwrap();

    let reader = std::io::Cursor::new(bytes);

I added some extra debugging after https://github.com/Nemo157/async-compression/blob/79326077ae6ed4f8499e31e83ab02f7a9c826ac9/src/codec/brotli/encoder.rs#L39

eprintln!("BrotliEncoderCompressStream input {}/{} output {}/{} in {:?}", input_len, in_buf.len(), output_len, out_buf.len(), start.elapsed());

which gave in --release:

BrotliEncoderCompressStream input 1700000/1700000 output 1310724/2000000 in 492.528302ms
BrotliEncoderCompressStream input 0/0 output 389284/689276 in 57.598134ms
elapsed: 550.742049ms

So there's no real overhead from async-compression, it's just brotli itself being this slow at the default level. Switching to Level::Fastest I get 1.5ms in release (which is probably the level that should be used for streaming compression).

@barvirm
Copy link
Author

barvirm commented Oct 7, 2022

I did a slight modification to test with random data (and try eliminate any IO times by reading everything at once):

    let file = File::open("/dev/urandom").await.unwrap();
    let reader = BufReader::with_capacity(2_000_000, file.take(1_700_000));

I don't get 20s, but I do see 2.5s in debug mode and 500ms in release which still seems way too long.

With this modification, I have the same results under WLS.

@barvirm
Copy link
Author

barvirm commented Oct 7, 2022

Intrestingly on Windows 10 x64, with modification like this:

    let file = File::open("test.bin").await.unwrap(); 
    let reader = BufReader::with_capacity(2_000_000, file.take(1_700_000));

It still takes 23s.

@barvirm
Copy link
Author

barvirm commented Oct 7, 2022

Ou so only this line changes the time from 3 to 23s. Doesn't matter if it's Windows / Unix (WLS)

// 23
let file = File::open("test.bin").await.unwrap(); 
// 3
let file = File::open("/dev/urandom").await.unwrap();

@barvirm
Copy link
Author

barvirm commented Oct 8, 2022

In the end, there is no problem with compression speed. The problem was the underlying data in test.bin file. If I created a file of the same size and fill it with random data, the compression speed is fine. When is the compression level set to Fastest timing results are almost identical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants