News for hackers. Stuff that matters.
Re:Ferron – a fast, memory-safe web server written in Rust by koakuma-chan on Saturday April 05, 2025 @06:18AM (#43592305)
In Rust all web frameworks are fast because they all use the same stack tokio + hyper.
Re:Ferron – a fast, memory-safe web server written in Rust by dorianniemiec on Saturday April 05, 2025 @07:17AM (#43592483)
By the way, Ferron web server also uses Tokio and Hyper.
Re:Ferron – a fast, memory-safe web server written in Rust by cle on Saturday April 05, 2025 @01:48PM (#43595204)
Hold my beer while I trivially write a slow web server on tokio + hyper.
Re:Ferron – a fast, memory-safe web server written in Rust by 01HNNWZ0MV43FF on Saturday April 05, 2025 @04:02PM (#43596390)
I could write one without Tokio, I'd just poll the sockets at 100 Hz
Re:Ferron – a fast, memory-safe web server written in Rust by cle on Saturday April 05, 2025 @07:26PM (#43597669)
Why not two birds with one stone: do the same in tokio + hyper, and disprove the ridiculous claim!
Re:Ferron – a fast, memory-safe web server written in Rust by alexpadula on Saturday April 05, 2025 @01:55PM (#43595248)
Holding :>
Re:Ferron – a fast, memory-safe web server written in Rust by ninkendo on Saturday April 05, 2025 @02:34PM (#43595588)
Fun experiment, try and benchmark a simple file download on a simple web server using rocket.rs (which also uses tokio and hyper, and has a built in fileserver type, so just a few lines of code) and compare it to a vanilla nginx config.

Here’s the rocket.rs source I used:

    #[rocket::main]
    async fn main() -> Result<(), rocket::Error> {
        rocket::build()
            .mount("/", rocket::fs::FileServer::from("/tmp/test"))
            .ignite()
            .await?
            .launch()
            .await?;
        Ok(())
    }
And do `mkdir /tmp/test && dd if=/dev/urandom of=/tmp/test/bigfile bs=1G count1` to create a 1G file, and run `time curl -o /dev/null localhost:8000/bigfile`.

My nginx config:

    worker_processes auto;
    master_process off;
    pid /dev/null;

    events {}

    http {
        sendfile on;
        access_log /dev/stdout;
        error_log /dev/stderr;
        server {
            listen 8089;
            server_name localhost;
            root /tmp/test;

            location / {
                try_files $uri $uri/ =404;
            }
        }
    }
launched with `nginx -c "$(pwd)"/nginx.conf -g "daemon off;"`

The results for a 1GB file for me on an nvme ssd, averaged over 100 runs:

    nginx: 150ms
    rocket: 4 seconds
Or roughly 25x slower. Release mode makes no difference.

You can definitely write slow code in rust if you’re naive about reading/writing between channels a few kilobytes at a time, which is what rocket does, vs using sendfile(2), like nginx does.

Edit: These numbers were from a few months ago... I tried it again by just pasting the above into a new project with `cargo init` and adding rocket and tokio to my deps, and it's now 2.3s in debug and 1.2s in release mode. It may have improved since a few months ago, but it's still 10x slower.

Re:Ferron – a fast, memory-safe web server written in Rust by piotrpdev on Saturday April 05, 2025 @03:59PM (#43596362)
Enabling lto, using codegen-units=1, and using the minimum required feature flags might improve performance a bit.
Re:Ferron – a fast, memory-safe web server written in Rust by ninkendo on Sunday April 06, 2025 @06:54AM (#43600478)
No, it won’t. Rocket is issuing 2 syscalls for every 4 kilobytes, which is what is killing the performance.
Re:Ferron – a fast, memory-safe web server written in Rust by koakuma-chan on Saturday April 05, 2025 @05:47PM (#43597079)
This doesn't count because hyper doesn't support sendfile. Maybe hyper would outperform nginx in other scenarios.
Re:Ferron – a fast, memory-safe web server written in Rust by ninkendo on Sunday April 06, 2025 @06:53AM (#43600473)
Disabling sendfile in nginx makes it take 170ms instead of 150ms on my system.

Because nginx knows to tune the buffer sizes properly, which goes a long way.

Using strace reveals what’s happening, rocket is reading and writing to file descriptors 4 kilobytes at a time, using 2 syscalls every chunk. nginx uses far, far fewer of them. (And with sendfile enabled, only one for the whole download.)

Also, there’s no reason rocket can’t use sendfile too. It’s basically the theoretically fastest way to perform this operation, and IMO rocket ought to use it by default if it’s available on the OS.

Re:Ferron – a fast, memory-safe web server written in Rust by koakuma-chan on Sunday April 06, 2025 @09:42AM (#43601364)
> Because nginx knows to tune the buffer sizes properly, which goes a long way.

Interesting. Do you know which algorithm nginx uses to determine the proper buffer size?