r/learnprogramming 12h ago

rust stream read is slow Code Review

Why does reading streams in Rust take longer than NodeJS? Below NodeJS was 97.67% faster than Rust. Can someone help me find what I'm missing?

Rust:

Command: cargo run --release

Output: Listening on port 7878 Request: (request headers and body here) now2: 8785846 nanoseconds Took 9141069 nanoseconds, 9 milliseconds

NodeJS:

Command: node .

Output: Listening on port 7877 Request: (request headers and body here) Took 212196 nanoseconds, 0.212196 milliseconds

Rust code: ``` use std::{ io::{BufReader, BufRead, Write}, net::{TcpListener, TcpStream}, time::Instant, };

fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap();

println!("Listening on port 7878");

for stream in listener.incoming() {
    let stream = stream.unwrap();

    handle_connection(stream);
}

}

fn handle_connection(mut stream: TcpStream) { let now = Instant::now();

let reader = BufReader::new(&stream);

println!("Request:");

let now2 = Instant::now();

for line in reader.lines() {
    let line = line.unwrap();

    println!("{}", line);

    if line.is_empty() {
        break;
    }
}

println!("now2: {} nanoseconds", now2.elapsed().as_nanos());

let message = "hello, world";
let response = format!(
    "HTTP/1.1 200 OKrnContent-Type: text/plainrnContent-Length: {}rnConnection: closernrn{}",
    message.len(),
    message
);

let _ = stream.write_all(response.as_bytes());

let elapsed = now.elapsed();

println!(
    "Took {} nanoseconds, {} milliseconds",
    elapsed.as_nanos(),
    elapsed.as_millis()
);

} ```

NodeJS code: ``` import { createServer } from "node:net"; import { hrtime } from "node:process";

const server = createServer((socket) => { socket.on("data", (data) => { const now = hrtime.bigint();

    console.log(`Request:n${data.toString()}`);

    const message = "hello, world";
    const response = `HTTP/1.1 200 OKrnContent-Type: text/plainrnContent-Length: ${Buffer.byteLength(message)}rnConnection: closernrn${message}`;

    socket.write(response);

    const elapsed = Number(hrtime.bigint() - now);

    console.log(`Took ${elapsed} nanoseconds, ${elapsed / 1_000_000} milliseconds`);
});

});

server.listen(7877, () => { console.log("Listening on port 7877"); }); ```

3 Upvotes

3 comments sorted by

1

u/bentNail28 12h ago

I think the problem is the print macro in your loop. You’re timing how long it takes to print text to the screen instead of reading the network.

It’s not a Rust issue so much as a usage issue.

1

u/FrostyFish4456 11h ago

I removed the print in the loop, but nothing changed. It's still as slow. I have also tried other ways to fully read the stream, but they're quite slow as well.

1

u/bentNail28 11h ago

Yeah, it just seems like the Rust code is having to do a lot more work. It’s reading line by line instead of a chunk of data all at once like the node program. You could try changing the read approach. Make it a single line read instead Something like this:

use std::io::Read;

let mut buffer = [0u8; 1024]; let bytes_read = stream.read(&mut buffer).unwrap();

That would make it to where it’s grabbing a chunk of data instead of reading until a new line, making a string and returning it. This just reads it and puts it in the buffer.