almost a magnitude of perf win by moving input polling into thread

This commit is contained in:
Stephan Dilly 2020-03-19 12:55:38 +01:00
parent 8618e404d4
commit eefd31ad05
3 changed files with 66 additions and 19 deletions

View file

@ -13,7 +13,7 @@ Over the last 2 years my go to GUI tool for this was [fork](https://git-fork.com
* [x] (un)stage files
* [x] inspect diffs
* [x] commit
* [ ] input polling in thread
* [x] input polling in thread
* [ ] file watcher instead of polling git
* [ ] log view

View file

@ -6,7 +6,7 @@ mod git_utils;
mod poll;
mod tui_utils;
use app::App;
use crate::{app::App, poll::QueueEvent};
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture},
terminal::{
@ -15,8 +15,7 @@ use crossterm::{
},
ExecutableCommand, Result,
};
use poll::PollResult;
use std::{io, time::Duration};
use std::io;
use tui::{backend::CrosstermBackend, Terminal};
fn main() -> Result<()> {
@ -33,18 +32,17 @@ fn main() -> Result<()> {
let mut app = App::new();
let receiver = poll::start_polling_thread();
loop {
app.update();
terminal.draw(|mut f| app.draw(&mut f))?;
loop {
if let PollResult::Event(e) =
poll::poll(Duration::from_millis(10))
{
app.event(e);
} else {
break;
let events = receiver.recv().unwrap();
for e in events {
if let QueueEvent::Event(ev) = e {
app.event(ev);
}
}

View file

@ -1,20 +1,69 @@
use crossterm::event::{self, Event};
use std::time::Duration;
use std::{
sync::mpsc::{self, Receiver},
thread::{self, sleep},
time::{Duration, Instant},
};
/// as
pub enum PollResult {
Timeout,
///
#[derive(Clone)]
pub enum QueueEvent {
Tick,
Event(Event),
}
static MAX_POLL_DURATION: Duration = Duration::from_secs(2);
static MIN_POLL_DURATION: Duration = Duration::from_millis(5);
static MAX_BATCHING_DURATION: Duration = Duration::from_millis(25);
static TICK_DURATION: Duration = Duration::from_secs(2);
/// we run 2 threads feeding us with update events.
///
pub fn poll(dur: Duration) -> PollResult {
/// Thread 1:
/// We will
pub fn start_polling_thread() -> Receiver<Vec<QueueEvent>> {
let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();
thread::spawn(move || {
let mut last_send = Instant::now();
let mut batch = Vec::new();
loop {
let timeout = if batch.len() > 0 {
MIN_POLL_DURATION
} else {
MAX_POLL_DURATION
};
if let Some(e) = poll(timeout) {
batch.push(QueueEvent::Event(e));
}
if batch.len() > 0
&& last_send.elapsed() > MAX_BATCHING_DURATION
{
tx1.send(batch).unwrap();
batch = Vec::new();
last_send = Instant::now();
}
}
});
thread::spawn(move || loop {
tx.send(vec![QueueEvent::Tick]).unwrap();
sleep(TICK_DURATION);
});
rx
}
///
fn poll(dur: Duration) -> Option<Event> {
if event::poll(dur).unwrap() {
// It's guaranteed that read() wont block if `poll` returns `Ok(true)`
let event = event::read().unwrap();
PollResult::Event(event)
Some(event)
} else {
PollResult::Timeout
None
}
}