rust: Preallocate the returned `Vec` in `utils::files::relativize_path`
authorSimon Sapin <simon.sapin@octobus.net>
Sat, 13 Mar 2021 08:59:03 +0100
changeset 46775 c94fa884240b
parent 46774 decc3bd3f20d
child 46776 471cd86c8eb4
rust: Preallocate the returned `Vec` in `utils::files::relativize_path` Profiling `rhg files > /dev/null` on an old snapshot of mozilla-central (with `perf` and the Firefox Profiler: https://github.com/firefox-devtools/profiler/blob/main/docs-user/guide-perf-profiling.md) showed non-trivial time spend in this function and in `realloc`. This change makes the wall-clock time for that process on my machine go from ~190 ms to ~150 ms. Differential Revision: https://phab.mercurial-scm.org/D10199
rust/hg-core/src/utils/files.rs
--- a/rust/hg-core/src/utils/files.rs	Tue Dec 01 12:59:33 2020 -0500
+++ b/rust/hg-core/src/utils/files.rs	Sat Mar 13 08:59:03 2021 +0100
@@ -290,7 +290,13 @@
     if cwd.as_ref().is_empty() {
         Cow::Borrowed(path.as_bytes())
     } else {
-        let mut res: Vec<u8> = Vec::new();
+        // This is not all accurate as to how large `res` will actually be, but
+        // profiling `rhg files` on a large-ish repo shows it’s better than
+        // starting from a zero-capacity `Vec` and letting `extend` reallocate
+        // repeatedly.
+        let guesstimate = path.as_bytes().len();
+
+        let mut res: Vec<u8> = Vec::with_capacity(guesstimate);
         let mut path_iter = path.as_bytes().split(|b| *b == b'/').peekable();
         let mut cwd_iter =
             cwd.as_ref().as_bytes().split(|b| *b == b'/').peekable();