Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/progress.rs @ 52316:f4aede0f01af
rust-manifest: use `memchr` crate for all byte-finding needs
While writing a very dumb manifest diffing algorithm for a proof-of-concept
I saw that `Manifest::find_by_path` was much slower than I was expecting.
It turns out that the Rust stdlib uses slow (all is relative) code when
searching for byte positions for reasons ranging from portability, SIMD
API stability, nobody doing the work, etc. `memch` is much faster for these
purposes, so let's use it.
I was measuring ~670ms of profile time in `find_by_path`, after this patch
it went down to ~230ms.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 12 Nov 2024 23:20:04 +0100 |
parents | 92e23ba257d1 |
children | a876ab6c3fd5 |
rev | line source |
---|---|
52065
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Progress-bar related things |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
52066
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
3 use std::{ |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
4 sync::atomic::{AtomicBool, Ordering}, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
5 time::Duration, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
6 }; |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
7 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
8 use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
9 |
52065
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 /// A generic determinate progress bar trait |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 pub trait Progress: Send + Sync + 'static { |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
12 /// Set the current position and optionally the total |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
13 fn update(&self, pos: u64, total: Option<u64>); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 /// Increment the current position and optionally the total |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 fn increment(&self, step: u64, total: Option<u64>); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
16 /// Declare that progress is over and the progress bar should be deleted |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 fn complete(self); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 } |
52066
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
19 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
20 const PROGRESS_DELAY: Duration = Duration::from_secs(1); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
21 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
22 /// A generic (determinate) progress bar. Stays hidden until [`PROGRESS_DELAY`] |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
23 /// to prevent flickering a progress bar for super fast operations. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
24 pub struct HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
25 progress: ProgressBar, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
26 has_been_shown: AtomicBool, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
27 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
28 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
29 impl HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
30 // TODO pass config to check progress.disable/assume-tty/delay/etc. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
31 /// Return a new progress bar with `topic` as the prefix. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
32 /// The progress and total are both set to 0, and it is hidden until the |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
33 /// next call to `update` given that more than a second has elapsed. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
34 pub fn new(topic: &str) -> Self { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
35 let template = |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
36 format!("{} {{wide_bar}} {{pos}}/{{len}} {{eta}} ", topic); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
37 let style = ProgressStyle::with_template(&template).unwrap(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
38 let progress_bar = ProgressBar::new(0).with_style(style); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
39 // Hide the progress bar and only show it if we've elapsed more |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
40 // than a second |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
41 progress_bar.set_draw_target(ProgressDrawTarget::hidden()); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
42 Self { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
43 progress: progress_bar, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
44 has_been_shown: false.into(), |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
45 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
46 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
47 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
48 /// Called whenever the progress changes to determine whether to start |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
49 /// showing the progress bar |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
50 fn maybe_show(&self) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
51 if self.progress.is_hidden() |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
52 && self.progress.elapsed() > PROGRESS_DELAY |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
53 { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
54 // Catch a race condition whereby we check if it's hidden, then |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
55 // set the draw target from another thread, then do it again from |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
56 // this thread, which results in multiple progress bar lines being |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
57 // left drawn. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
58 let has_been_shown = |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
59 self.has_been_shown.fetch_or(true, Ordering::Relaxed); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
60 if !has_been_shown { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
61 // Here we are certain that we're the only thread that has |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
62 // set `has_been_shown` and we can change the draw target |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
63 self.progress.set_draw_target(ProgressDrawTarget::stderr()); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
64 self.progress.tick(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
65 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
66 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
67 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
68 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
69 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
70 impl Progress for HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
71 fn update(&self, pos: u64, total: Option<u64>) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
72 self.progress.update(|state| { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
73 state.set_pos(pos); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
74 if let Some(t) = total { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
75 state.set_len(t) |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
76 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
77 }); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
78 self.maybe_show(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
79 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
80 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
81 fn increment(&self, step: u64, total: Option<u64>) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
82 self.progress.inc(step); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
83 if let Some(t) = total { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
84 self.progress.set_length(t) |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
85 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
86 self.maybe_show(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
87 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
88 |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
89 fn complete(self) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
90 self.progress.finish_and_clear(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
91 } |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52065
diff
changeset
|
92 } |