performance improvements
This commit is contained in:
parent
37f9d1ae4f
commit
fe163f3831
1 changed files with 79 additions and 24 deletions
103
src/main.rs
103
src/main.rs
|
|
@ -1,8 +1,9 @@
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
use std::{mem, io};
|
use std::{mem, io};
|
||||||
use ::std::fmt::{self, Display, Formatter};
|
use ::std::fmt::{self, Display, Formatter};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::io::{stdin, stdout, Read, Write};
|
use std::io::{stdin, stdout, Read, Write};
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{BTreeSet, HashMap, VecDeque};
|
||||||
use nix::unistd::{read, write, ForkResult};
|
use nix::unistd::{read, write, ForkResult};
|
||||||
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
||||||
use nix::sys::termios::SpecialCharacterIndices::{VMIN, VTIME};
|
use nix::sys::termios::SpecialCharacterIndices::{VMIN, VTIME};
|
||||||
|
|
@ -36,7 +37,8 @@ fn read_from_pid (pid: RawFd) -> Option<Vec<u8>> {
|
||||||
let read_result = read(pid, &mut read_buffer);
|
let read_result = read(pid, &mut read_buffer);
|
||||||
match read_result {
|
match read_result {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
Some(read_buffer[..=res].to_vec())
|
let res = Some(read_buffer[..=res].to_vec());
|
||||||
|
res
|
||||||
// (res, read_buffer)
|
// (res, read_buffer)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -184,9 +186,10 @@ struct TerminalOutput {
|
||||||
pub characters: Vec<char>, // we use a vec rather than a string here because one char can take up multiple characters in a string
|
pub characters: Vec<char>, // we use a vec rather than a string here because one char can take up multiple characters in a string
|
||||||
pub display_rows: u16,
|
pub display_rows: u16,
|
||||||
pub display_cols: u16,
|
pub display_cols: u16,
|
||||||
|
pub should_render: bool,
|
||||||
cursor_position: usize,
|
cursor_position: usize,
|
||||||
newline_indices: HashSet<usize>, // canonical line breaks we get from the vt interpreter
|
newline_indices: BTreeSet<usize>, // canonical line breaks we get from the vt interpreter
|
||||||
linebreak_indices: HashSet<usize>, // linebreaks from line wrapping
|
linebreak_indices: BTreeSet<usize>, // linebreaks from line wrapping
|
||||||
unhandled_ansi_codes: HashMap<usize, String>,
|
unhandled_ansi_codes: HashMap<usize, String>,
|
||||||
pending_ansi_code: Option<String>, // this is used eg. in a carriage return, where we need to preserve the style
|
pending_ansi_code: Option<String>, // this is used eg. in a carriage return, where we need to preserve the style
|
||||||
}
|
}
|
||||||
|
|
@ -196,10 +199,11 @@ impl TerminalOutput {
|
||||||
TerminalOutput {
|
TerminalOutput {
|
||||||
characters: vec![],
|
characters: vec![],
|
||||||
cursor_position: 0,
|
cursor_position: 0,
|
||||||
newline_indices: HashSet::new(),
|
newline_indices: BTreeSet::new(),
|
||||||
linebreak_indices: HashSet::new(),
|
linebreak_indices: BTreeSet::new(),
|
||||||
display_rows: 0,
|
display_rows: 0,
|
||||||
display_cols: 0,
|
display_cols: 0,
|
||||||
|
should_render: false,
|
||||||
unhandled_ansi_codes: HashMap::new(),
|
unhandled_ansi_codes: HashMap::new(),
|
||||||
pending_ansi_code: None,
|
pending_ansi_code: None,
|
||||||
}
|
}
|
||||||
|
|
@ -207,10 +211,12 @@ impl TerminalOutput {
|
||||||
pub fn reduce_width(&mut self, count: u16) {
|
pub fn reduce_width(&mut self, count: u16) {
|
||||||
self.display_cols -= count;
|
self.display_cols -= count;
|
||||||
self.reflow_lines();
|
self.reflow_lines();
|
||||||
|
self.should_render = true;
|
||||||
}
|
}
|
||||||
pub fn increase_width(&mut self, count: u16) {
|
pub fn increase_width(&mut self, count: u16) {
|
||||||
self.display_cols += count;
|
self.display_cols += count;
|
||||||
self.reflow_lines();
|
self.reflow_lines();
|
||||||
|
self.should_render = true;
|
||||||
}
|
}
|
||||||
pub fn set_size(&mut self, ws: &Winsize) {
|
pub fn set_size(&mut self, ws: &Winsize) {
|
||||||
let orig_cols = self.display_cols;
|
let orig_cols = self.display_cols;
|
||||||
|
|
@ -269,6 +275,7 @@ impl TerminalOutput {
|
||||||
output.push_front(Vec::from(empty_line.clone()));
|
output.push_front(Vec::from(empty_line.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.should_render = false;
|
||||||
Vec::from(output)
|
Vec::from(output)
|
||||||
}
|
}
|
||||||
pub fn cursor_position_in_last_line (&self) -> usize {
|
pub fn cursor_position_in_last_line (&self) -> usize {
|
||||||
|
|
@ -285,13 +292,17 @@ impl TerminalOutput {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// return last
|
// return last
|
||||||
Some(self.newline_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i })) // TODO: better?
|
// None
|
||||||
|
Some(*self.newline_indices.iter().last().unwrap())
|
||||||
|
// Some(self.newline_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i })) // TODO: better?
|
||||||
};
|
};
|
||||||
let last_linebreak_index = if self.linebreak_indices.is_empty() {
|
let last_linebreak_index = if self.linebreak_indices.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// return last
|
// return last
|
||||||
Some(self.linebreak_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i })) // TODO: better?
|
// None
|
||||||
|
Some(*self.linebreak_indices.iter().last().unwrap())
|
||||||
|
// Some(self.linebreak_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i })) // TODO: better?
|
||||||
};
|
};
|
||||||
match (last_newline_index, last_linebreak_index) {
|
match (last_newline_index, last_linebreak_index) {
|
||||||
(Some(last_newline_index), Some(last_linebreak_index)) => {
|
(Some(last_newline_index), Some(last_linebreak_index)) => {
|
||||||
|
|
@ -307,13 +318,42 @@ impl TerminalOutput {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// return last less than index_in_line
|
// return last less than index_in_line
|
||||||
Some(self.newline_indices.iter().fold(0, |acc, n_i| if *n_i > acc && *n_i <= index_in_line { *n_i } else { acc })) // TODO: better?
|
// None
|
||||||
|
let last_newline_index = *self.newline_indices.iter().last().unwrap();
|
||||||
|
if last_newline_index <= index_in_line {
|
||||||
|
Some(last_newline_index)
|
||||||
|
} else {
|
||||||
|
let mut last_newline_index = 0;
|
||||||
|
for n_i in self.newline_indices.iter() {
|
||||||
|
if *n_i > last_newline_index && *n_i <= index_in_line {
|
||||||
|
last_newline_index = *n_i;
|
||||||
|
} else if *n_i > index_in_line {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(last_newline_index)
|
||||||
|
}
|
||||||
|
// Some(self.newline_indices.iter().fold(0, |acc, n_i| if *n_i > acc && *n_i <= index_in_line { *n_i } else { acc })) // TODO: better?
|
||||||
};
|
};
|
||||||
let last_linebreak_index = if self.linebreak_indices.is_empty() {
|
let last_linebreak_index = if self.linebreak_indices.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// return last less than index_in_line
|
// return last less than index_in_line
|
||||||
Some(self.linebreak_indices.iter().fold(0, |acc, l_i| if *l_i > acc && *l_i <= index_in_line { *l_i } else { acc })) // TODO: better?
|
// None
|
||||||
|
let last_linebreak_index = *self.linebreak_indices.iter().last().unwrap();
|
||||||
|
if last_linebreak_index <= index_in_line {
|
||||||
|
Some(last_linebreak_index)
|
||||||
|
} else {
|
||||||
|
let mut last_linebreak_index = 0;
|
||||||
|
for l_i in self.linebreak_indices.iter() {
|
||||||
|
if *l_i > last_linebreak_index && *l_i <= index_in_line {
|
||||||
|
last_linebreak_index = *l_i;
|
||||||
|
} else if *l_i > index_in_line {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(last_linebreak_index)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
match (last_newline_index, last_linebreak_index) {
|
match (last_newline_index, last_linebreak_index) {
|
||||||
(Some(last_newline_index), Some(last_linebreak_index)) => {
|
(Some(last_newline_index), Some(last_linebreak_index)) => {
|
||||||
|
|
@ -327,6 +367,7 @@ impl TerminalOutput {
|
||||||
fn add_newline (&mut self) {
|
fn add_newline (&mut self) {
|
||||||
self.newline_indices.insert(self.characters.len()); // -1?
|
self.newline_indices.insert(self.characters.len()); // -1?
|
||||||
self.cursor_position = self.characters.len(); // -1?
|
self.cursor_position = self.characters.len(); // -1?
|
||||||
|
self.should_render = true;
|
||||||
}
|
}
|
||||||
fn move_to_beginning_of_line (&mut self) {
|
fn move_to_beginning_of_line (&mut self) {
|
||||||
let last_newline_index = if self.newline_indices.is_empty() {
|
let last_newline_index = if self.newline_indices.is_empty() {
|
||||||
|
|
@ -335,6 +376,7 @@ impl TerminalOutput {
|
||||||
self.newline_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i }) // TODO: better?
|
self.newline_indices.iter().fold(0, |acc, i| if acc > *i { acc } else { *i }) // TODO: better?
|
||||||
};
|
};
|
||||||
self.cursor_position = last_newline_index;
|
self.cursor_position = last_newline_index;
|
||||||
|
self.should_render = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,6 +409,7 @@ impl vte::Perform for TerminalOutput {
|
||||||
}
|
}
|
||||||
self.cursor_position += 1;
|
self.cursor_position += 1;
|
||||||
}
|
}
|
||||||
|
// println!("\rDONE PRINT {:?}", now.elapsed().as_millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, byte: u8) {
|
fn execute(&mut self, byte: u8) {
|
||||||
|
|
@ -590,7 +633,6 @@ impl Screen {
|
||||||
let mut last_character_was_changed = false;
|
let mut last_character_was_changed = false;
|
||||||
for i in 0..last_frame.len() {
|
for i in 0..last_frame.len() {
|
||||||
let current_character = frame.get(i).unwrap();
|
let current_character = frame.get(i).unwrap();
|
||||||
// TODO:
|
|
||||||
if !character_is_already_onscreen(&last_frame, &frame, i) {
|
if !character_is_already_onscreen(&last_frame, &frame, i) {
|
||||||
let row = i / full_screen_ws.ws_col as usize + 1;
|
let row = i / full_screen_ws.ws_col as usize + 1;
|
||||||
let col = i % full_screen_ws.ws_col as usize + 1;
|
let col = i % full_screen_ws.ws_col as usize + 1;
|
||||||
|
|
@ -694,23 +736,29 @@ fn main() {
|
||||||
match (read_from_pid(first_terminal_pid), read_from_pid(second_terminal_pid)) {
|
match (read_from_pid(first_terminal_pid), read_from_pid(second_terminal_pid)) {
|
||||||
(Some(first_terminal_read_bytes), Some(second_terminal_read_bytes)) => {
|
(Some(first_terminal_read_bytes), Some(second_terminal_read_bytes)) => {
|
||||||
let mut terminal1_output = terminal1_output.lock().unwrap();
|
let mut terminal1_output = terminal1_output.lock().unwrap();
|
||||||
|
let mut terminal2_output = terminal2_output.lock().unwrap();
|
||||||
for byte in first_terminal_read_bytes.iter() {
|
for byte in first_terminal_read_bytes.iter() {
|
||||||
vte_parser_terminal1.advance(&mut *terminal1_output, *byte);
|
vte_parser_terminal1.advance(&mut *terminal1_output, *byte);
|
||||||
}
|
}
|
||||||
let mut terminal2_output = terminal2_output.lock().unwrap();
|
|
||||||
for byte in second_terminal_read_bytes.iter() {
|
for byte in second_terminal_read_bytes.iter() {
|
||||||
vte_parser_terminal2.advance(&mut *terminal2_output, *byte);
|
vte_parser_terminal2.advance(&mut *terminal2_output, *byte);
|
||||||
}
|
}
|
||||||
buffer_has_unread_data = true;
|
buffer_has_unread_data = true;
|
||||||
}
|
}
|
||||||
(Some(first_terminal_read_bytes), None) => {
|
(Some(first_terminal_read_bytes), None) => {
|
||||||
|
let now = Instant::now();
|
||||||
let mut terminal1_output = terminal1_output.lock().unwrap();
|
let mut terminal1_output = terminal1_output.lock().unwrap();
|
||||||
let mut terminal2_output = terminal2_output.lock().unwrap();
|
// let mut terminal2_output = terminal2_output.lock().unwrap();
|
||||||
|
// println!("\rread bytes, parsing...");
|
||||||
|
let now = Instant::now();
|
||||||
for byte in first_terminal_read_bytes.iter() {
|
for byte in first_terminal_read_bytes.iter() {
|
||||||
vte_parser_terminal1.advance(&mut *terminal1_output, *byte);
|
vte_parser_terminal1.advance(&mut *terminal1_output, *byte);
|
||||||
}
|
}
|
||||||
let active_terminal = active_terminal.lock().unwrap();
|
// println!("\rdone parsing bytes in {:?}", now.elapsed());
|
||||||
screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
// println!("\rprint time: {:?}", terminal1_output.debug_print_time.as_millis());
|
||||||
|
buffer_has_unread_data = true;
|
||||||
|
// let active_terminal = active_terminal.lock().unwrap();
|
||||||
|
// screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
||||||
}
|
}
|
||||||
(None, Some(second_terminal_read_bytes)) => {
|
(None, Some(second_terminal_read_bytes)) => {
|
||||||
let mut terminal1_output = terminal1_output.lock().unwrap();
|
let mut terminal1_output = terminal1_output.lock().unwrap();
|
||||||
|
|
@ -718,20 +766,27 @@ fn main() {
|
||||||
for byte in second_terminal_read_bytes.iter() {
|
for byte in second_terminal_read_bytes.iter() {
|
||||||
vte_parser_terminal2.advance(&mut *terminal2_output, *byte);
|
vte_parser_terminal2.advance(&mut *terminal2_output, *byte);
|
||||||
}
|
}
|
||||||
let active_terminal = active_terminal.lock().unwrap();
|
buffer_has_unread_data = true;
|
||||||
screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
// let active_terminal = active_terminal.lock().unwrap();
|
||||||
|
// screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
||||||
}
|
}
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
let mut terminal1_output = terminal1_output.lock().unwrap();
|
// let mut terminal1_output = terminal1_output.lock().unwrap();
|
||||||
let mut terminal2_output = terminal2_output.lock().unwrap();
|
// let mut terminal2_output = terminal2_output.lock().unwrap();
|
||||||
if buffer_has_unread_data {
|
// if buffer_has_unread_data {
|
||||||
let active_terminal = active_terminal.lock().unwrap();
|
// let active_terminal = active_terminal.lock().unwrap();
|
||||||
screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
// screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
||||||
buffer_has_unread_data = false;
|
// buffer_has_unread_data = false;
|
||||||
}
|
// }
|
||||||
::std::thread::sleep(std::time::Duration::from_millis(50)); // TODO: adjust this
|
::std::thread::sleep(std::time::Duration::from_millis(50)); // TODO: adjust this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut terminal1_output = terminal1_output.lock().unwrap();
|
||||||
|
let mut terminal2_output = terminal2_output.lock().unwrap();
|
||||||
|
if terminal1_output.should_render || terminal2_output.should_render {
|
||||||
|
let active_terminal = active_terminal.lock().unwrap();
|
||||||
|
screen.lock().unwrap().render(&mut *terminal1_output, &mut *terminal2_output, &full_screen_ws, *active_terminal == first_terminal_pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue