Simplified the screen buffer writing.
Turns out the main reason it was so slow was because stdout isn't buffered in Rust by default. That actually makes a lot of sense, but I'd forgotten. Wrapping it in a BufWriter solves the performance issues much more gracefully.
This commit is contained in:
parent
1f62eb32a0
commit
2591aef6d4
|
@ -1,7 +1,7 @@
|
||||||
use std;
|
use std;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::{BufWriter, Write};
|
||||||
|
|
||||||
use super::smallstring::SmallString;
|
use super::smallstring::SmallString;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
@ -12,7 +12,7 @@ use termion::color;
|
||||||
use termion::raw::{IntoRawMode, RawTerminal};
|
use termion::raw::{IntoRawMode, RawTerminal};
|
||||||
|
|
||||||
pub(crate) struct Screen {
|
pub(crate) struct Screen {
|
||||||
out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>,
|
out: RefCell<AlternateScreen<RawTerminal<BufWriter<io::Stdout>>>>,
|
||||||
buf: RefCell<Vec<Option<(Style, SmallString)>>>,
|
buf: RefCell<Vec<Option<(Style, SmallString)>>>,
|
||||||
w: usize,
|
w: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
|
@ -25,7 +25,11 @@ impl Screen {
|
||||||
.take(w as usize * h as usize)
|
.take(w as usize * h as usize)
|
||||||
.collect();
|
.collect();
|
||||||
Screen {
|
Screen {
|
||||||
out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())),
|
out: RefCell::new(AlternateScreen::from(
|
||||||
|
BufWriter::with_capacity(1 << 14, io::stdout())
|
||||||
|
.into_raw_mode()
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
buf: RefCell::new(buf),
|
buf: RefCell::new(buf),
|
||||||
w: w as usize,
|
w: w as usize,
|
||||||
h: h as usize,
|
h: h as usize,
|
||||||
|
@ -56,39 +60,31 @@ impl Screen {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn present(&self) {
|
pub(crate) fn present(&self) {
|
||||||
|
let mut out = self.out.borrow_mut();
|
||||||
let buf = self.buf.borrow();
|
let buf = self.buf.borrow();
|
||||||
|
|
||||||
// Double the minimum needed space, because of formatting characters and such.
|
let mut last_style = Style(Color::Black, Color::Black);
|
||||||
let mut tmp_string = String::with_capacity(self.w * self.h * 2);
|
write!(out, "{}", last_style).unwrap();
|
||||||
tmp_string.push_str(&format!("{}", termion::cursor::Goto(1, 1)));
|
|
||||||
|
|
||||||
// Write everything to the tmp_string first.
|
// Write everything to the tmp_string first.
|
||||||
for y in 0..self.h {
|
for y in 0..self.h {
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
let mut last_style = Style(Color::Black, Color::Black);
|
write!(out, "{}", termion::cursor::Goto(1, y as u16 + 2)).unwrap();
|
||||||
tmp_string.push_str(&format!("{}", last_style));
|
|
||||||
while x < self.w {
|
while x < self.w {
|
||||||
if let Some((style, ref text)) = buf[y * self.w + x] {
|
if let Some((style, ref text)) = buf[y * self.w + x] {
|
||||||
if style != last_style {
|
if style != last_style {
|
||||||
tmp_string.push_str(&format!("{}", style));
|
write!(out, "{}", style).unwrap();
|
||||||
last_style = style;
|
last_style = style;
|
||||||
}
|
}
|
||||||
tmp_string.push_str(text);
|
write!(out, "{}", text).unwrap();
|
||||||
x += 1;
|
x += 1;
|
||||||
} else {
|
} else {
|
||||||
x += 1;
|
x += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp_string.push_str(&format!("{}", termion::cursor::Goto(1, y as u16 + 2)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write tmp_string to the screen all at once.
|
// Make sure everything is written out
|
||||||
write!(
|
|
||||||
self.out.borrow_mut(),
|
|
||||||
"{}{}",
|
|
||||||
termion::cursor::Goto(0, 0),
|
|
||||||
tmp_string,
|
|
||||||
).unwrap();
|
|
||||||
self.out.borrow_mut().flush().unwrap();
|
self.out.borrow_mut().flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user