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

ServeDir sending file speed is extremely slow #136

Closed
ttys3 opened this issue Sep 1, 2021 · 0 comments
Closed

ServeDir sending file speed is extremely slow #136

ttys3 opened this issue Sep 1, 2021 · 0 comments

Comments

@ttys3
Copy link
Contributor

ttys3 commented Sep 1, 2021

update 1

the tower-http ServeDir static file sending speed has been improved now.

with my tokio-util PR(tokio-rs/tokio#4086) merged.

and this "future" PR: ttys3@2aa8c65

since there's no new release on tokio-util, I have to use the patch method for now. When tokio-util released a new version, I'll send a PR to tower-http.

Yes! The final speed, nearly the same!

axum+tower-http: 1318M/s

actix: 1435M/s

  /tmp 
❯ curl -L http://127.0.0.1:3000/a.mp4 > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 4694M    0 4694M    0     0  1318M      0 --:--:--  0:00:03 --:--:-- 1318M
  /tmp took 3s 
❯ curl -L http://127.0.0.1:8080/a.mp4 > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 4694M  100 4694M    0     0  1435M      0  0:00:03  0:00:03 --:--:-- 1435M

update 2

my previus test is not accurate. because I use the debug build for both actix and tower-http.

but it is not fair to tower-http.

with another test with both release build, tower-http speed up to 9x

axum + tower-http ServerDir:

first run: 5994k/s
second run: 6083k/s
third run: 6093k/s

actix:

first run: 799M/s
second run: 1447M/s
third run:  1442M/s

each run means a new curl request.

tower-http: curl -L http://127.0.0.1:3000/a.mp4 > /dev/null

actix: curl -L http://127.0.0.1:8080/a.mp4 > /dev/null

the result did not change much, the gap is still serious.

in the release binary, tower-http has a slight speed up from 700K/s to about 6000K/s. it is about 9X speed up.

but for actix, the run after the first one, speed up from 800M/s to 1400M/s,

I guess the reason why tower-http at low speed, is that is does not reuse the chunk buf,

and AsyncReadBody creates a new BytesMut for each poll.

and also, the default chunk buf is not big enough.


test env

OS : ArchLinux
Kernel: 5.13.13-arch1-1 #1 SMP PREEMPT Thu, 26 Aug 2021 19:14:36 +0000 x86_64 GNU/Linux
curl:

❯ curl --version
curl 7.78.0 (x86_64-pc-linux-gnu) libcurl/7.78.0 OpenSSL/1.1.1l zlib/1.2.11 zstd/1.5.0 libidn2/2.3.2 libpsl/0.21.1 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.44.0
Release-Date: 2021-07-21
  1. using lo interface, so the traffic is limited by CPU speed, not the physical net card and line.
  2. write downloaded bytes to /dev/null, so the writing speed is not a bottleneck.

ServeDir sending file speed is extremely slow

here's demo code to re-produce the issue: https://github.com/ttys3/static-file-server-speed-compare

with ServeDir to serve a single static file downloading with single thread downlader,
the file sending speed is extremly slow.

I got the download speed at only 684KiB/s (run a second test the result is 743K/s)

so I simply increased the chunk buf size to 2M like this:

-        let mut buf = BytesMut::new();
+        let mut buf = BytesMut::with_capacity(1024*1024*2);

then the download speed seems improved.

image

I talked this to david, he suggest reuse memory allocation.

use something like https://docs.rs/tokio-util/0.6.7/tokio_util/io/struct.ReaderStream.html

to convert the AsyncRead into a Stream, and then converting the Stream into a Body.

the ReaderStream default chunk size is 4096 bytes, I can not change it, it can only stable at 50MiB/s

I try to send a PR tokio-rs/tokio#4086

which add with_capacity for ReaderStream

when the buf size >= 16KiB, the speed can stable at 200MiB/s

buf = 4KiB, 50MiB/s
buf = 8KiB, 100MiB/s
buf >=16 KiB, 200MiB/s

I was not satisfied with the speed. I think there's a problem. because it is lo (127.0.0.1), and my cpu is 8 core 16 threads. and the file is written to /dev/null, so there's no writing io problem

so I took a simple demo from actix doc and compare the result:

image

in my code, tower-http speed was somehow limited to 200MiB/s
but actix demo can run at a stable download speed near 800MiB/s
the actix code is simple:

use actix_files as fs;
use actix_web::{App, HttpServer};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(fs::Files::new("/", "/home").show_files_listing()))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

and also I found that actix behavors diff due to different ACTIX_THREADPOOL:

env ACTIX_THREADPOOL=16 cargo run   => speed at 899MiB/s
env ACTIX_THREADPOOL=1 cargo run   => speed at 1158MiB/s

Version

tower-http v0.1.1

here's my modified tower-http: ttys3@0ae7cff

Platform

5.13.13-arch1-1 #1 SMP PREEMPT Thu, 26 Aug 2021 19:14:36 +0000 x86_64 GNU/Linux
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

1 participant