Skip to content

Commit e8c299b

Browse files
committed
perf: use background task for worker
1 parent c518f84 commit e8c299b

File tree

4 files changed

+90
-44
lines changed

4 files changed

+90
-44
lines changed

helix-term/src/handlers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
2323
let event_tx = completion::CompletionHandler::new(config).spawn();
2424
let signature_hints = SignatureHelpHandler::new().spawn();
2525
let auto_save = AutoSaveHandler::new().spawn();
26-
let blame = blame::BlameHandler.spawn();
26+
let blame = blame::BlameHandler::default().spawn();
2727

2828
let handlers = Handlers {
2929
completions: helix_view::handlers::completion::CompletionHandler::new(event_tx),

helix-term/src/handlers/blame.rs

+79-40
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,110 @@
1+
use std::{path::PathBuf, time::Duration};
2+
13
use helix_event::{register_hook, send_blocking};
4+
use helix_vcs::DiffProviderRegistry;
25
use helix_view::{
36
handlers::{BlameEvent, Handlers},
47
Editor,
58
};
9+
use tokio::{task::JoinHandle, time::Instant};
610

711
use crate::{events::PostCommand, job};
812

9-
pub struct BlameHandler;
13+
#[derive(Default)]
14+
pub struct BlameHandler {
15+
worker: Option<JoinHandle<anyhow::Result<String>>>,
16+
}
17+
18+
async fn compute_diff(
19+
file: PathBuf,
20+
line: u32,
21+
diff_providers: DiffProviderRegistry,
22+
) -> anyhow::Result<String> {
23+
// std::thread::sleep(Duration::from_secs(5));
24+
// Ok("hhe".to_string())
25+
diff_providers
26+
.blame_line(&file, line)
27+
.map(|s| s.to_string())
28+
}
1029

1130
impl helix_event::AsyncHook for BlameHandler {
1231
type Event = BlameEvent;
1332

1433
fn handle_event(
1534
&mut self,
16-
_event: Self::Event,
35+
event: Self::Event,
1736
_timeout: Option<tokio::time::Instant>,
1837
) -> Option<tokio::time::Instant> {
19-
self.finish_debounce();
20-
None
38+
if let Some(worker) = &self.worker {
39+
if worker.is_finished() {
40+
self.finish_debounce();
41+
return None;
42+
}
43+
return Some(Instant::now() + Duration::from_millis(50));
44+
}
45+
46+
let BlameEvent::PostCommand {
47+
file,
48+
cursor_line,
49+
diff_providers,
50+
} = event;
51+
52+
let worker = tokio::spawn(compute_diff(file, cursor_line, diff_providers));
53+
self.worker = Some(worker);
54+
Some(Instant::now() + Duration::from_millis(50))
2155
}
2256

2357
fn finish_debounce(&mut self) {
24-
// TODO: this blocks on the main thread. Figure out how not to do that
25-
//
26-
// Attempts so far:
27-
// - tokio::spawn
28-
// - std::thread::spawn
29-
//
30-
// For some reason none of the above fix the issue of blocking the UI.
31-
job::dispatch_blocking(move |editor, _| {
32-
request_git_blame(editor);
33-
})
58+
if let Some(worker) = &self.worker {
59+
if worker.is_finished() {
60+
let worker = self.worker.take().unwrap();
61+
tokio::spawn(handle_worker(worker));
62+
}
63+
}
3464
}
3565
}
3666

67+
async fn handle_worker(worker: JoinHandle<anyhow::Result<String>>) {
68+
let Ok(Ok(outcome)) = worker.await else {
69+
return;
70+
};
71+
job::dispatch(move |editor, _| {
72+
let doc = doc_mut!(editor);
73+
doc.blame = Some(outcome);
74+
})
75+
.await;
76+
}
77+
3778
pub(super) fn register_hooks(handlers: &Handlers) {
3879
let tx = handlers.blame.clone();
3980
register_hook!(move |event: &mut PostCommand<'_, '_>| {
4081
if event.cx.editor.config().vcs.blame {
41-
send_blocking(&tx, BlameEvent::PostCommand);
82+
let blame_enabled = event.cx.editor.config().vcs.blame;
83+
let (view, doc) = current!(event.cx.editor);
84+
let text = doc.text();
85+
let selection = doc.selection(view.id);
86+
let Some(file) = doc.path() else {
87+
panic!();
88+
};
89+
if !blame_enabled {
90+
panic!();
91+
}
92+
93+
let cursor_lin = text.char_to_line(selection.primary().cursor(doc.text().slice(..)));
94+
let Ok(cursor_line) = TryInto::<u32>::try_into(cursor_lin) else {
95+
panic!();
96+
};
97+
98+
send_blocking(
99+
&tx,
100+
BlameEvent::PostCommand {
101+
file: file.to_path_buf(),
102+
cursor_line,
103+
diff_providers: event.cx.editor.diff_providers.clone(),
104+
},
105+
);
42106
}
43107

44108
Ok(())
45109
});
46110
}
47-
48-
fn request_git_blame(editor: &mut Editor) {
49-
let blame_enabled = editor.config().vcs.blame;
50-
let (view, doc) = current!(editor);
51-
let text = doc.text();
52-
let selection = doc.selection(view.id);
53-
let Some(file) = doc.path() else {
54-
return;
55-
};
56-
if !blame_enabled {
57-
return;
58-
}
59-
60-
let cursor_lin = text.char_to_line(selection.primary().cursor(doc.text().slice(..)));
61-
let Ok(cursor_line) = TryInto::<u32>::try_into(cursor_lin) else {
62-
return;
63-
};
64-
65-
// 0-based into 1-based line number
66-
let Ok(output) = editor.diff_providers.blame_line(file, cursor_line + 1) else {
67-
return;
68-
};
69-
70-
doc.blame = Some(output.to_string());
71-
}

helix-vcs/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mod status;
1717

1818
pub use status::FileChange;
1919

20-
#[derive(Clone)]
20+
#[derive(Clone, Debug)]
2121
pub struct DiffProviderRegistry {
2222
providers: Vec<DiffProvider>,
2323
}
@@ -94,7 +94,7 @@ impl Default for DiffProviderRegistry {
9494
/// cloning [DiffProviderRegistry] as `Clone` cannot be used in trait objects.
9595
///
9696
/// `Copy` is simply to ensure the `clone()` call is the simplest it can be.
97-
#[derive(Copy, Clone)]
97+
#[derive(Copy, Clone, Debug)]
9898
pub enum DiffProvider {
9999
#[cfg(feature = "git")]
100100
Git,

helix-view/src/handlers.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use std::path::PathBuf;
2+
13
use completion::{CompletionEvent, CompletionHandler};
24
use helix_event::send_blocking;
5+
use helix_vcs::DiffProviderRegistry;
36
use tokio::sync::mpsc::Sender;
47

58
use crate::handlers::lsp::SignatureHelpInvoked;
@@ -18,7 +21,11 @@ pub enum AutoSaveEvent {
1821

1922
#[derive(Debug)]
2023
pub enum BlameEvent {
21-
PostCommand,
24+
PostCommand {
25+
file: PathBuf,
26+
cursor_line: u32,
27+
diff_providers: DiffProviderRegistry,
28+
},
2229
}
2330

2431
pub struct Handlers {

0 commit comments

Comments
 (0)