Pure write sys call

Hello all,
I simply try to make a console write without loosing runtime to unwrap the result of bytes written on the console... which doesn't interest me for fast tty escape sequence graphic,
I have few options:
-find a way to use:

stdout().write(b"data").unwrap();

but without the .unwrap() which is a runtime penalty...
or
-write my own asm syscall , or maybe libc syscall ...
any idea ?

What do you want to happen if stdout is closed and the write fails?

nothing ? certainly not panicking...

Well its sim that rust impose to check the validity of the syscall I can understand that as safe language but for fast console video game that can't not always be a good choice... is really that the lack of flexibility in Rust ?

"write" even in pure assembler can return error,
and you still need to handle error case, that exactly what "unwrap" do.
How can assembly can help to not handle errors?

1 Like

By simply not assigning memory to the sys-call returned bytes length result ?

maybe drop(stdout().write(b"data")) would be nice

and that sim to work well thanks

Then just let _ = stdout().write(b"data");.

(The Result-building will likely optimize out in that case, and if not, it's completely negligible compared to the cost of the syscall.)

3 Likes

oh nice ! thanks !

But you should realize that this is not optimization.
Following variants would give you the same assembly.
So from speed or memory usage the are the same for three of them:

{
let _ = stdout().write(b"data");//1
}
{
drop(stdout().write(b"data"));//2
}
{
stdout().write(b"data");//3
}

in fact that was just a compiler warning not an error of the compiler
so it's impossible to do better... right ?

If stdout() isn't just a stand-in for something else, you should probably lock stdout
and bufferize the writing, and find a buffer size which has the right balance for your needs.

use std::io::Write;

fn main() {
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    write!(out, "data");
}

That will have a much larger impact on performance than ignoring errors.

3 Likes

Stdout is already buffered.

Thank you, I (seemingly) always forget that about that type. I now remember a whole thread here about that, some months ago. I'll link it if I find it.

It is possible, but what for? Usage of extra ~ 16/24 bytes in stack is neglectable,
in compare to switching kernel/user space + execution of "tty" driver code in linux kernel + code to rendering output in your preferable terminal.

I am not sure that you can measure this achievement (removing of usage of 24 bytes on stack).
Time of copy several bytes + substract/add to stack pointer is not 1% of write system call,
I am not even sure that it is 0.000_0001% of write system call.

you mean than from os point of view the only way to do better is to make a custom sys call from os... and call it from rust ? so from rust there are no possible optimisation on how the officials sys call write can be efficiently called ?
by the way does locking the stdout() improve speed on it ?

On Rust you can use libc::write or directly call write syscall via syscall macro.
But what I mean this optimization have no sense, because of when you do benchmark you can not see the difference, and if there is no difference what is the point for optimization?

If you want to get real speedup for your program, then this is depend on your program. If you provide flamegraph from perf it would be possible for other advise something.

For example if you read data from socket/file and then print to stdout you can speedup it via sendfile.

Yes, because of otherwise you have to lock each time you call write.
But again you can or can not see any difference in real program, because of
that depend on your program.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.