Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/utils/debug.rs @ 52280: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 | a6b8b1ab9116 |
children |
rev | line source |
---|---|
50214
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Utils for debugging hg-core |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
3 use crate::config::Config; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
4 |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
5 /// Write the file path given by the config option `devel.<config_option>` with |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
6 /// the suffix `.waiting`, then wait for the file path given by the |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
7 /// config option `devel.<config_option>` to appear on disk |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
8 /// up to `devel.<config_option>-timeout` seconds. |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
9 /// Note that the timeout may be higher because we scale it if global |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 /// `run-tests` timeouts are raised to prevent flakiness on slower hardware. |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 /// |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
12 /// Useful for testing race conditions. |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
13 pub fn debug_wait_for_file( |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 config: &Config, |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 config_option: &str, |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
16 ) -> Result<(), String> { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 let path_opt = format!("sync.{config_option}"); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 let file_path = match config.get_str(b"devel", path_opt.as_bytes()).ok() { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
19 Some(Some(file_path)) => file_path, |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
20 _ => return Ok(()), |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
21 }; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
22 |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
23 // TODO make it so `configitems` is shared between Rust and Python so that |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
24 // defaults work out of the box, etc. |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
25 let default_timeout = 2; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
26 let timeout_opt = format!("sync.{config_option}-timeout"); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
27 let timeout_seconds = |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
28 match config.get_u32(b"devel", timeout_opt.as_bytes()) { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
29 Ok(Some(timeout)) => timeout, |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
30 Err(e) => { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
31 log::debug!("{e}"); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
32 default_timeout |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
33 } |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
34 _ => default_timeout, |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
35 }; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
36 let timeout_seconds = timeout_seconds as u64; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
37 |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
38 log::debug!( |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
39 "Config option `{config_option}` found, \ |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
40 waiting for file `{file_path}` to be created" |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
41 ); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
42 std::fs::File::create(format!("{file_path}.waiting")).ok(); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
43 // If the test timeout have been extended, scale the timer relative |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
44 // to the normal timing. |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
45 let global_default_timeout: u64 = std::env::var("HGTEST_TIMEOUT_DEFAULT") |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
46 .map(|t| t.parse()) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
47 .unwrap_or(Ok(0)) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
48 .unwrap(); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
49 let global_timeout_override: u64 = std::env::var("HGTEST_TIMEOUT") |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
50 .map(|t| t.parse()) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
51 .unwrap_or(Ok(0)) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
52 .unwrap(); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
53 let timeout_seconds = if global_default_timeout < global_timeout_override { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
54 timeout_seconds * global_timeout_override / global_default_timeout |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
55 } else { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
56 timeout_seconds |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
57 }; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
58 let timeout = std::time::Duration::from_secs(timeout_seconds); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
59 |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
60 let start = std::time::Instant::now(); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
61 let path = std::path::Path::new(file_path); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
62 let mut found = false; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
63 while start.elapsed() < timeout { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
64 if path.exists() { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
65 log::debug!("File `{file_path}` was created"); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
66 found = true; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
67 break; |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
68 } else { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
69 std::thread::sleep(std::time::Duration::from_millis(10)); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
70 } |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
71 } |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
72 if !found { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
73 let msg = format!( |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
74 "File `{file_path}` set by `{config_option}` was not found \ |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
75 within the allocated {timeout_seconds} seconds timeout" |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
76 ); |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
77 Err(msg) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
78 } else { |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
79 Ok(()) |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
80 } |
8e0d823ef182
testing: introduce util function to synchronize concurrent commands on files
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
81 } |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50214
diff
changeset
|
82 |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50214
diff
changeset
|
83 pub fn debug_wait_for_file_or_print(config: &Config, config_option: &str) { |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50228
diff
changeset
|
84 if let Err(e) = debug_wait_for_file(config, config_option) { |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50214
diff
changeset
|
85 eprintln!("{e}"); |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50214
diff
changeset
|
86 }; |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50214
diff
changeset
|
87 } |