Patchwork D12494: [RFC] rust-revlog: create nodemap on the fly if it's not persisted

login
register
mail settings
Submitter phabricator
Date April 11, 2022, 4:07 p.m.
Message ID <differential-rev-PHID-DREV-or54uq3uu5zylt672svm-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50841/
State New
Headers show

Comments

phabricator - April 11, 2022, 4:07 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  We can create a nodemap in memory when there isn't a persistent
  one. When listing all commits in the hg repo, it sped up the
  equivalent of `hg log -T '{node}\n' --hidden` (but run with my hobby
  project's hg backend) from 123 s to 2.55 s.
  
  What do we actually want to do here? Calculate the map after we've
  done a few O(n) node-to-rev requests? I think that's what the C
  implementation does.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D12494

AFFECTED FILES
  rust/hg-core/src/revlog/revlog.rs

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/hg-core/src/revlog/revlog.rs b/rust/hg-core/src/revlog/revlog.rs
--- a/rust/hg-core/src/revlog/revlog.rs
+++ b/rust/hg-core/src/revlog/revlog.rs
@@ -18,7 +18,7 @@ 
 use crate::errors::HgError;
 use crate::repo::Repo;
 use crate::revlog::Revision;
-use crate::{Node, NULL_REVISION};
+use crate::{Node, RevlogIndex, NULL_REVISION};
 
 const REVISION_FLAG_CENSORED: u16 = 1 << 15;
 const REVISION_FLAG_ELLIPSIS: u16 = 1 << 14;
@@ -112,14 +112,23 @@ 
         let nodemap = if index.is_inline() {
             None
         } else {
-            NodeMapDocket::read_from_file(repo, index_path)?.map(
-                |(docket, data)| {
-                    nodemap::NodeTree::load_bytes(
-                        Box::new(data),
-                        docket.data_length,
-                    )
-                },
-            )
+            if let Some((docket, data)) =
+                NodeMapDocket::read_from_file(repo, index_path)?
+            {
+                Some(nodemap::NodeTree::load_bytes(
+                    Box::new(data),
+                    docket.data_length,
+                ))
+            } else {
+                let mut nodemap = nodemap::NodeTree::default();
+                for rev in 0..index.len() {
+                    let rev = rev as Revision;
+                    nodemap
+                        .insert(&index, index.node(rev).unwrap(), rev)
+                        .unwrap();
+                }
+                Some(nodemap)
+            }
         };
 
         Ok(Revlog {