perf: avoid eager diff loading and full-file typing work
This commit is contained in:
+25
-12
@@ -5,7 +5,7 @@ use std::{
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||
mpsc::{self, Receiver, SyncSender},
|
||||
mpsc::{self, Receiver, Sender},
|
||||
},
|
||||
thread::{self, JoinHandle},
|
||||
};
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
type DiffResult = (u64, Result<DiffOutcome, String>);
|
||||
|
||||
struct DiffWorker {
|
||||
requests: Option<SyncSender<(u64, DiffOperation)>>,
|
||||
requests: Option<Sender<(u64, DiffOperation)>>,
|
||||
results: Option<Receiver<DiffResult>>,
|
||||
cancelled: Arc<AtomicBool>,
|
||||
stopped: Arc<AtomicBool>,
|
||||
@@ -36,7 +36,7 @@ struct DiffWorker {
|
||||
|
||||
impl DiffWorker {
|
||||
fn start(root: PathBuf) -> Result<Self, String> {
|
||||
let (requests, incoming) = mpsc::sync_channel::<(u64, DiffOperation)>(1);
|
||||
let (requests, incoming) = mpsc::channel::<(u64, DiffOperation)>();
|
||||
let (outgoing, results) = mpsc::sync_channel(1);
|
||||
let cancelled = Arc::new(AtomicBool::new(false));
|
||||
let stopped = Arc::new(AtomicBool::new(false));
|
||||
@@ -56,7 +56,7 @@ impl DiffWorker {
|
||||
if stop.load(Ordering::Acquire) {
|
||||
break;
|
||||
}
|
||||
if cancelled_id.load(Ordering::Acquire) == id {
|
||||
if cancelled_id.load(Ordering::Acquire) >= id {
|
||||
continue;
|
||||
}
|
||||
let result = (|| {
|
||||
@@ -68,6 +68,9 @@ impl DiffWorker {
|
||||
DiffOperation::Discover => {
|
||||
repository.catalog().map(DiffOutcome::Catalog)
|
||||
}
|
||||
DiffOperation::ListRemote(remote) => {
|
||||
repository.list_remote(&remote).map(DiffOutcome::Catalog)
|
||||
}
|
||||
DiffOperation::FetchRemote(remote) => {
|
||||
repository.fetch_remote(&remote).map(DiffOutcome::Catalog)
|
||||
}
|
||||
@@ -76,8 +79,18 @@ impl DiffWorker {
|
||||
after,
|
||||
buffers,
|
||||
} => repository
|
||||
.compare(&before, &after, &buffers)
|
||||
.compare(id, &before, &after, &buffers)
|
||||
.map(DiffOutcome::Comparison),
|
||||
DiffOperation::LoadFile {
|
||||
comparison_id,
|
||||
file_index,
|
||||
} => repository.load_file(comparison_id, file_index).map(|file| {
|
||||
DiffOutcome::File {
|
||||
comparison_id,
|
||||
file_index,
|
||||
file,
|
||||
}
|
||||
}),
|
||||
}
|
||||
})();
|
||||
if stop.load(Ordering::Acquire) || outgoing.send((id, result)).is_err() {
|
||||
@@ -98,16 +111,15 @@ impl DiffWorker {
|
||||
}
|
||||
|
||||
fn request(&mut self, id: u64, operation: DiffOperation) -> Result<(), String> {
|
||||
if let Some(previous) = self.pending.take() {
|
||||
self.cancelled_request.store(previous, Ordering::Release);
|
||||
self.cancelled.store(true, Ordering::Release);
|
||||
}
|
||||
self.requests
|
||||
.as_ref()
|
||||
.expect("live diff worker has a sender")
|
||||
.try_send((id, operation))
|
||||
.map_err(|error| match error {
|
||||
mpsc::TrySendError::Full(_) => "Diff worker is already busy".to_owned(),
|
||||
mpsc::TrySendError::Disconnected(_) => {
|
||||
"Diff worker stopped unexpectedly".to_owned()
|
||||
}
|
||||
})?;
|
||||
.send((id, operation))
|
||||
.map_err(|_| "Diff worker stopped unexpectedly".to_owned())?;
|
||||
self.pending = Some(id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -3387,6 +3399,7 @@ end
|
||||
path: PathBuf::from("buffer.txt"),
|
||||
old_path: None,
|
||||
status: FileStatus::Modified,
|
||||
loaded: true,
|
||||
before: vec!["base".into()],
|
||||
after: vec!["base".into()],
|
||||
before_eof: false,
|
||||
|
||||
Reference in New Issue
Block a user