Skip to content

Commit 2497c4f

Browse files
author
Stephan Dilly
committed
fix performance regression in revlog
1 parent df43ea0 commit 2497c4f

File tree

3 files changed

+79
-37
lines changed

3 files changed

+79
-37
lines changed

asyncgit/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub mod sync;
1212

1313
pub use crate::{
1414
diff::{AsyncDiff, DiffParams},
15-
revlog::AsyncLog,
15+
revlog::{AsyncLog, FetchStatus},
1616
status::{AsyncStatus, StatusParams},
1717
sync::{
1818
diff::{DiffLine, DiffLineType, FileDiff},

asyncgit/src/revlog.rs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,32 @@ use std::{
1313
atomic::{AtomicBool, Ordering},
1414
Arc, Mutex,
1515
},
16+
thread,
17+
time::Duration,
1618
};
1719

20+
///
21+
#[derive(PartialEq)]
22+
pub enum FetchStatus {
23+
/// previous fetch still running
24+
Pending,
25+
/// no change expected
26+
NoChange,
27+
/// new walk was started
28+
Started,
29+
}
30+
1831
///
1932
pub struct AsyncLog {
2033
current: Arc<Mutex<Vec<Oid>>>,
2134
sender: Sender<AsyncNotification>,
2235
pending: Arc<AtomicBool>,
36+
background: Arc<AtomicBool>,
2337
}
2438

25-
static LIMIT_COUNT: usize = 1000;
39+
static LIMIT_COUNT: usize = 3000;
40+
static SLEEP_FOREGROUND: Duration = Duration::from_millis(2);
41+
static SLEEP_BACKGROUND: Duration = Duration::from_millis(1000);
2642

2743
impl AsyncLog {
2844
///
@@ -31,6 +47,7 @@ impl AsyncLog {
3147
current: Arc::new(Mutex::new(Vec::new())),
3248
sender,
3349
pending: Arc::new(AtomicBool::new(false)),
50+
background: Arc::new(AtomicBool::new(false)),
3451
}
3552
}
3653

@@ -58,6 +75,11 @@ impl AsyncLog {
5875
self.pending.load(Ordering::Relaxed)
5976
}
6077

78+
///
79+
pub fn set_background(&mut self) {
80+
self.background.store(true, Ordering::Relaxed)
81+
}
82+
6183
///
6284
fn current_head(&self) -> Result<Oid> {
6385
Ok(self.current.lock()?.first().map_or(Oid::zero(), |f| *f))
@@ -79,29 +101,44 @@ impl AsyncLog {
79101
}
80102

81103
///
82-
pub fn fetch(&mut self) -> Result<()> {
83-
if !self.is_pending() && self.head_changed()? {
84-
self.clear()?;
104+
pub fn fetch(&mut self) -> Result<FetchStatus> {
105+
self.background.store(false, Ordering::Relaxed);
85106

86-
let arc_current = Arc::clone(&self.current);
87-
let sender = self.sender.clone();
88-
let arc_pending = Arc::clone(&self.pending);
89-
90-
rayon_core::spawn(move || {
91-
scope_time!("async::revlog");
107+
if self.is_pending() {
108+
return Ok(FetchStatus::Pending);
109+
}
92110

93-
arc_pending.store(true, Ordering::Relaxed);
94-
AsyncLog::fetch_helper(arc_current, &sender)
95-
.expect("failed to fetch");
96-
arc_pending.store(false, Ordering::Relaxed);
97-
Self::notify(&sender);
98-
});
111+
if !self.head_changed()? {
112+
return Ok(FetchStatus::NoChange);
99113
}
100-
Ok(())
114+
115+
self.clear()?;
116+
117+
let arc_current = Arc::clone(&self.current);
118+
let sender = self.sender.clone();
119+
let arc_pending = Arc::clone(&self.pending);
120+
let arc_background = Arc::clone(&self.background);
121+
122+
rayon_core::spawn(move || {
123+
scope_time!("async::revlog");
124+
125+
arc_pending.store(true, Ordering::Relaxed);
126+
AsyncLog::fetch_helper(
127+
arc_current,
128+
arc_background,
129+
&sender,
130+
)
131+
.expect("failed to fetch");
132+
arc_pending.store(false, Ordering::Relaxed);
133+
Self::notify(&sender);
134+
});
135+
136+
Ok(FetchStatus::Started)
101137
}
102138

103139
fn fetch_helper(
104140
arc_current: Arc<Mutex<Vec<Oid>>>,
141+
arc_background: Arc<AtomicBool>,
105142
sender: &Sender<AsyncNotification>,
106143
) -> Result<()> {
107144
let mut entries = Vec::with_capacity(LIMIT_COUNT);
@@ -121,6 +158,14 @@ impl AsyncLog {
121158
break;
122159
} else {
123160
Self::notify(&sender);
161+
162+
let sleep_duration =
163+
if arc_background.load(Ordering::Relaxed) {
164+
SLEEP_BACKGROUND
165+
} else {
166+
SLEEP_FOREGROUND
167+
};
168+
thread::sleep(sleep_duration);
124169
}
125170
}
126171

src/tabs/revlog/mod.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
ui::calc_scroll_top,
1111
ui::style::Theme,
1212
};
13-
use asyncgit::{sync, AsyncLog, AsyncNotification, CWD};
13+
use asyncgit::{sync, AsyncLog, AsyncNotification, CWD, FetchStatus};
1414
use crossbeam_channel::Sender;
1515
use crossterm::event::Event;
1616
use std::{borrow::Cow, cmp, convert::TryFrom, time::Instant};
@@ -32,7 +32,6 @@ pub struct Revlog {
3232
items: ItemBatch,
3333
git_log: AsyncLog,
3434
visible: bool,
35-
first_open_done: bool,
3635
scroll_state: (Instant, f32),
3736
tags: Tags,
3837
current_size: (u16, u16),
@@ -52,7 +51,6 @@ impl Revlog {
5251
selection: 0,
5352
count_total: 0,
5453
visible: false,
55-
first_open_done: false,
5654
scroll_state: (Instant::now(), 0_f32),
5755
tags: Tags::new(),
5856
current_size: (0, 0),
@@ -73,20 +71,22 @@ impl Revlog {
7371
///
7472
pub fn update(&mut self) {
7573
if self.visible {
76-
self.git_log.fetch().unwrap();
77-
}
74+
let log_changed =
75+
self.git_log.fetch().unwrap() == FetchStatus::Started;
7876

79-
let old_total = self.count_total;
80-
self.count_total = self.git_log.count().unwrap();
77+
self.count_total = self.git_log.count().unwrap();
8178

82-
if self.items.needs_data(self.selection, self.selection_max())
83-
|| old_total != self.count_total
84-
{
85-
self.fetch_commits();
86-
}
79+
if self
80+
.items
81+
.needs_data(self.selection, self.selection_max())
82+
|| log_changed
83+
{
84+
self.fetch_commits();
85+
}
8786

88-
if self.tags.is_empty() {
89-
self.tags = sync::get_tags(CWD).unwrap();
87+
if self.tags.is_empty() {
88+
self.tags = sync::get_tags(CWD).unwrap();
89+
}
9090
}
9191
}
9292

@@ -340,14 +340,11 @@ impl Component for Revlog {
340340

341341
fn hide(&mut self) {
342342
self.visible = false;
343+
self.git_log.set_background();
343344
}
344345

345346
fn show(&mut self) {
346347
self.visible = true;
347-
348-
if !self.first_open_done {
349-
self.first_open_done = true;
350-
self.git_log.fetch().unwrap();
351-
}
348+
self.git_log.fetch().unwrap();
352349
}
353350
}

0 commit comments

Comments
 (0)