Show More
@@ -47,16 +47,10 b" pub fn status<'dirstate>(" | |||||
47 | options: StatusOptions, |
|
47 | options: StatusOptions, | |
48 | ) -> Result<(DirstateStatus<'dirstate>, Vec<PatternFileWarning>), StatusError> |
|
48 | ) -> Result<(DirstateStatus<'dirstate>, Vec<PatternFileWarning>), StatusError> | |
49 | { |
|
49 | { | |
50 | // Force the global rayon threadpool to not exceed 16 concurrent threads. |
|
50 | // Also cap for a Python caller of this function, but don't complain if | |
51 | // This is a stop-gap measure until we figure out why using more than 16 |
|
51 | // the global threadpool has already been set since this code path is also | |
52 | // threads makes `status` slower for each additional thread. |
|
52 | // being used by `rhg`, which calls this early. | |
53 | // We use `ok()` in case the global threadpool has already been |
|
53 | let _ = crate::utils::cap_default_rayon_threads(); | |
54 | // instantiated in `rhg` or some other caller. |
|
|||
55 | // TODO find the underlying cause and fix it, then remove this. |
|
|||
56 | rayon::ThreadPoolBuilder::new() |
|
|||
57 | .num_threads(16.min(rayon::current_num_threads())) |
|
|||
58 | .build_global() |
|
|||
59 | .ok(); |
|
|||
60 |
|
54 | |||
61 | let (ignore_fn, warnings, patterns_changed): (IgnoreFnType, _, _) = |
|
55 | let (ignore_fn, warnings, patterns_changed): (IgnoreFnType, _, _) = | |
62 | if options.list_ignored || options.list_unknown { |
|
56 | if options.list_ignored || options.list_unknown { |
@@ -498,3 +498,35 b' where' | |||||
498 | Err(e) => Some(Err(e)), |
|
498 | Err(e) => Some(Err(e)), | |
499 | }) |
|
499 | }) | |
500 | } |
|
500 | } | |
|
501 | ||||
|
502 | /// Force the global rayon threadpool to not exceed 16 concurrent threads | |||
|
503 | /// unless the user has specified a value. | |||
|
504 | /// This is a stop-gap measure until we figure out why using more than 16 | |||
|
505 | /// threads makes `status` slower for each additional thread. | |||
|
506 | /// | |||
|
507 | /// TODO find the underlying cause and fix it, then remove this. | |||
|
508 | /// | |||
|
509 | /// # Errors | |||
|
510 | /// | |||
|
511 | /// Returns an error if the global threadpool has already been initialized if | |||
|
512 | /// we try to initialize it. | |||
|
513 | pub fn cap_default_rayon_threads() -> Result<(), rayon::ThreadPoolBuildError> { | |||
|
514 | const THREAD_CAP: usize = 16; | |||
|
515 | ||||
|
516 | if std::env::var("RAYON_NUM_THREADS").is_err() { | |||
|
517 | let available_parallelism = std::thread::available_parallelism() | |||
|
518 | .map(usize::from) | |||
|
519 | .unwrap_or(1); | |||
|
520 | let new_thread_count = THREAD_CAP.min(available_parallelism); | |||
|
521 | let res = rayon::ThreadPoolBuilder::new() | |||
|
522 | .num_threads(new_thread_count) | |||
|
523 | .build_global(); | |||
|
524 | if res.is_ok() { | |||
|
525 | log::trace!( | |||
|
526 | "Capped the rayon threadpool to {new_thread_count} threads", | |||
|
527 | ); | |||
|
528 | } | |||
|
529 | return res; | |||
|
530 | } | |||
|
531 | Ok(()) | |||
|
532 | } |
@@ -140,6 +140,13 b' fn rhg_main(argv: Vec<OsString>) -> ! {' | |||||
140 |
|
140 | |||
141 | env_logger::init(); |
|
141 | env_logger::init(); | |
142 |
|
142 | |||
|
143 | // Make sure nothing in a future version of `rhg` sets the global | |||
|
144 | // threadpool before we can cap default threads. (This is also called | |||
|
145 | // in core because Python uses the same code path, we're adding a | |||
|
146 | // redundant check.) | |||
|
147 | hg::utils::cap_default_rayon_threads() | |||
|
148 | .expect("Rayon threadpool already initialized"); | |||
|
149 | ||||
143 | let early_args = EarlyArgs::parse(&argv); |
|
150 | let early_args = EarlyArgs::parse(&argv); | |
144 |
|
151 | |||
145 | let initial_current_dir = early_args.cwd.map(|cwd| { |
|
152 | let initial_current_dir = early_args.cwd.map(|cwd| { |
General Comments 0
You need to be logged in to leave comments.
Login now