mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
almost a magnitude of perf win by moving input polling into thread
This commit is contained in:
parent
8618e404d4
commit
eefd31ad05
3 changed files with 66 additions and 19 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
18
src/main.rs
18
src/main.rs
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
65
src/poll.rs
65
src/poll.rs
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue