Which is the fastest execution to write dynamic data to a socket among these options?

Hello, I'm searching for the fastest one for single threaded execution. Which one?

These are pseudo code (the syntax is not correct)

Number 1

let mut buf = String::with_capacity(1024)

fn run (input: &str) {
    write!(&mut buf, "data: {}", input)
    socket.write_all(buf.as_bytes())
}

let input = format!("number {}", 100)
run(&input)

Number 2

let mut buf = vec![0u8; 1024]

fn run (input: &str) {
    write!(&mut buf, "data: {}", input)
    socket.write_all(&buf)
}

let input = format!("number {}", 100)
run(&input)

Number 3

let mut buf = String::with_capacity(1024)

fn run (input: String) {
    write!(&mut buf, "data: {}", input)
    socket.write_all(buf.as_bytes())
}

let input = format!("number {}", 100)
run(input)

Number 4

let mut buf = vec![0u8; 1024]

fn run (input: String) {
    write!(&mut buf, "data: {}", input)
    socket.write_all(&buf)
}

let input = format!("number {}", 100)
run(input)

Number 5

let mut buf = vec![0u8; 1024]

fn run (input: &[u8]) {
    buf.extend_from_slices(input)
    socket.write_all(&buf)
}

let input = format!("number {}", 100)
run(input.as_bytes())

Number 6

let mut buf = vec![0u8; 1024]

fn run (mut input: Vec<u8>) {
    buf.append(&mut input)
    socket.write_all(&buf)
}

let input = format!("number {}", 100)
run(input.into_bytes())

Number 7

let mut buf = bytes::BytesMut::with_capacity(1024)

fn run (input: &[u8]) {
    buf.extend_from_slices(input)
    socket.write_all(&buf)
}

let input = format!("number {}", 100)
run(input.as_bytes())

Number 8, 9, 10 .... are the same except : using std::io::IoSlice and write_vectorized

These should all be identical in performance except for Number 4 and 6 which require deallocating a String or Vec every time.

However, none of them are the best option; you should be using std::io::BufWriter wrapped around the socket, and you can then use write!() directly on it instead of an intermediate buffer.

3 Likes

Can std:io::BufWriter be preallocated in a pool? for example I have prepared 1000 of them when initializing the program, then at runtime the program just reuse them without new allocation

Just create one along with each socket. The cost of an allocation is probably insignificant as long as you're not doing it for every write.

The one thing you will want to be careful about is either calling flush() or dropping the BufWriter when you're finished with all the data frames and you're waiting for the other side to reply.

No, but this crate supports that by allowing you reuse buffers:

Sorry: This is not applicable because the interfaces are not async.

If I do it for every connection to the server will get a new TcpStream, then creating BufWriter(TcpStream), is it good?

Isn't the buffwriter will automatically be dropped after leaving the scope? I use it inside tokio::spawn_local

Is this already non blocking? I use Tokio in my project

You're right, it isn't applicable.