Skip to content

Commit 1782c35

Browse files
committed
perf: use background task for worker
_
1 parent c518f84 commit 1782c35

File tree

4 files changed

+91
-48
lines changed

4 files changed

+91
-48
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

+80-44
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,107 @@
1+
use std::{path::PathBuf, time::Duration};
2+
13
use helix_event::{register_hook, send_blocking};
2-
use helix_view::{
3-
handlers::{BlameEvent, Handlers},
4-
Editor,
5-
};
4+
use helix_vcs::DiffProviderRegistry;
5+
use helix_view::handlers::{BlameEvent, Handlers};
6+
use tokio::{task::JoinHandle, time::Instant};
67

78
use crate::{events::PostCommand, job};
89

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

1127
impl helix_event::AsyncHook for BlameHandler {
1228
type Event = BlameEvent;
1329

1430
fn handle_event(
1531
&mut self,
16-
_event: Self::Event,
32+
event: Self::Event,
1733
_timeout: Option<tokio::time::Instant>,
1834
) -> Option<tokio::time::Instant> {
19-
self.finish_debounce();
20-
None
35+
if let Some(worker) = &self.worker {
36+
if worker.is_finished() {
37+
self.finish_debounce();
38+
return None;
39+
}
40+
return Some(Instant::now() + Duration::from_millis(50));
41+
}
42+
43+
let BlameEvent::PostCommand {
44+
file,
45+
cursor_line,
46+
diff_providers,
47+
} = event;
48+
49+
let worker = tokio::spawn(compute_diff(file, cursor_line, diff_providers));
50+
self.worker = Some(worker);
51+
Some(Instant::now() + Duration::from_millis(50))
2152
}
2253

2354
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-
})
55+
if let Some(worker) = &self.worker {
56+
if worker.is_finished() {
57+
let worker = self.worker.take().unwrap();
58+
tokio::spawn(handle_worker(worker));
59+
}
60+
}
3461
}
3562
}
3663

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

44105
Ok(())
45106
});
46107
}
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)