Add buffer for stdout?

Hello everyone :wave:

Apparently, when the buffer for stdout is flushed either manually, when you call .flush(), or if the buffer is full. The thing is, I don't want it to flush when the buffer is full, only when I want it to do so. How can I achieve that ?

I need that because, as you can see, sometimes, a bottom window will 'flicker' on top of an other window. That's because the output is flushed (and rendered) when the bottom window is redrawn, but not the top one yet. That's why I want to flush only when all windows are drawn https://imgur.com/gallery/osXjwiw

If you know the maximum number of bytes you want to write, you could wrap stdout in a BufWriter with the appropriate capacity.

If the number of bytes per draw is unbounded, you can instead do your own buffering by writing to a Vec<u8> (which will grow automatically), then write the entire Vec to stdout when you are ready to draw.

I think you pasted the wrong link?

Oh yeah, sorry, I edited my post.

I can't find how to set a custom buffer size in the doc. Also, the window are now following my mouse with a HUGE latency

Edit: I found the with_capacity method

You'll should now flush() the writer explicitly every time you are ready to draw, since it will only flush automatically when the buffer fills up (which ideally should never happen).

I do flush ! Here's how my function looks like :


pub fn redraw(stdout: &mut std::io::Stdout, w: u16, h: u16, screen: &Screen) -> Result<()> {
    let mut stdout = BufWriter::with_capacity(w as usize * h as usize, stdout);
    /* drawing stuff*/ 
    stdout.flush()?;
    stdout.get_mut().flush()?;
    Ok(())
}

EDIT: I tried with and without 
    `stdout.get_mut().flush()?;`

Maybe I shouldn't create a new bufwriter every time ?

Just stdout.flush() should be sufficient; the BufWriter's flush method will also flush the inner writer:

https://doc.rust-lang.org/1.44.1/src/std/io/buffered.rs.html#683-685

It would be a little more efficient to re-use the same BufWriter, yeah. You can change redraw to take a BufWriter<Stdout>, or make it generic over any Write type.

This change shouldn't affect the flushing behavior, though it might speed up the redraw function by some amount. (Mostly it just saves you from allocating and then freeing a buffer on every redraw.)

1 Like

I tried doing that, but the windows are still flickering... If anything, it is now much worse...

It’s hard to guess at the cause, but one thing to try is using a much larger BufWriter capacity, in case you are writing more than one byte per terminal cell (because of multi-byte characters or escape sequences, for example).

Also, you could do something like BufWriter::new(stdout.lock()) to reduce synchronization overhead.

1 Like

I tried multiplying the size by 100 and it (almost) wasn't flickering anymore. I still have a few SECONDS of latency with stdout.lock()

Is there any formula to get the size in bytes of the whole terminal with the width and height ? Because multiplying the value by a random number seems to work but it doesn't seem like a great solution.

Found the solution for the lag, it had to do with how I was polling events.

1 Like

Found out for the buffer size : it doesn't really depend of the size of the terminal, but on how much do I draw.

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.