# HG changeset patch # User Pierre-Yves David # Date 1709805436 -3600 # Node ID 4a8bb136ee779b9763a6dfcdb707ba5894f5e36d # Parent 718f28ea3af4dae7db2601d48e206289cfec04c8 branchcache: allow to detect "pure topological case" for branchmap We don't rum this detection every time we run the branchcache, that would be costly. However we now do it when running `hg debugupdatecache`. This will help existing repository to benefit from the fastpath when possible. diff -r 718f28ea3af4 -r 4a8bb136ee77 mercurial/branchmap.py --- a/mercurial/branchmap.py Thu Mar 07 04:15:23 2024 +0100 +++ b/mercurial/branchmap.py Thu Mar 07 10:57:16 2024 +0100 @@ -69,7 +69,7 @@ ) return bcache - def update_disk(self, repo): + def update_disk(self, repo, detect_pure_topo=False): """ensure and up-to-date cache is (or will be) written on disk The cache for this repository view is updated if needed and written on @@ -87,6 +87,8 @@ bcache._filtername, repo.filtername, ) + if detect_pure_topo: + bcache._detect_pure_topo(repo) tr = repo.currenttransaction() if getattr(tr, 'finalized', True): bcache.sync_disk(repo) @@ -488,6 +490,9 @@ def _ensure_populated(self, repo): """make sure any lazily loaded values are fully populated""" + def _detect_pure_topo(self, repo) -> None: + pass + def validfor(self, repo): """check that cache contents are valid for (a subset of) this repo @@ -1055,6 +1060,19 @@ self._entries[self._pure_topo_branch] = heads self._needs_populate = False + def _detect_pure_topo(self, repo) -> None: + if self._pure_topo_branch is not None: + # we are pure topological already + return + to_node = repo.changelog.node + topo_heads = [to_node(r) for r in self._get_topo_heads(repo)] + if any(n in self._closednodes for n in topo_heads): + return + for branch, heads in self._entries.items(): + if heads == topo_heads: + self._pure_topo_branch = branch + break + class remotebranchcache(_BaseBranchCache): """Branchmap info for a remote connection, should not write locally""" diff -r 718f28ea3af4 -r 4a8bb136ee77 mercurial/interfaces/repository.py --- a/mercurial/interfaces/repository.py Thu Mar 07 04:15:23 2024 +0100 +++ b/mercurial/interfaces/repository.py Thu Mar 07 10:57:16 2024 +0100 @@ -54,6 +54,8 @@ CACHE_BRANCHMAP_SERVED = b"branchmap-served" # Warm internal changelog cache (eg: persistent nodemap) CACHE_CHANGELOG_CACHE = b"changelog-cache" +# check of a branchmap can use the "pure topo" mode +CACHE_BRANCHMAP_DETECT_PURE_TOPO = b"branchmap-detect-pure-topo" # Warm full manifest cache CACHE_FULL_MANIFEST = b"full-manifest" # Warm file-node-tags cache @@ -78,6 +80,7 @@ CACHES_ALL = { CACHE_BRANCHMAP_SERVED, CACHE_BRANCHMAP_ALL, + CACHE_BRANCHMAP_DETECT_PURE_TOPO, CACHE_CHANGELOG_CACHE, CACHE_FILE_NODE_TAGS, CACHE_FULL_MANIFEST, diff -r 718f28ea3af4 -r 4a8bb136ee77 mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Mar 07 04:15:23 2024 +0100 +++ b/mercurial/localrepo.py Thu Mar 07 10:57:16 2024 +0100 @@ -2924,8 +2924,13 @@ if repository.CACHE_BRANCHMAP_SERVED in caches: if tr is None or tr.changes[b'origrepolen'] < len(self): self.ui.debug(b'updating the branch cache\n') - self._branchcaches.update_disk(self.filtered(b'served')) - self._branchcaches.update_disk(self.filtered(b'served.hidden')) + dpt = repository.CACHE_BRANCHMAP_DETECT_PURE_TOPO in caches + served = self.filtered(b'served') + self._branchcaches.update_disk(served, detect_pure_topo=dpt) + served_hidden = self.filtered(b'served.hidden') + self._branchcaches.update_disk( + served_hidden, detect_pure_topo=dpt + ) if repository.CACHE_CHANGELOG_CACHE in caches: self.changelog.update_caches(transaction=tr) @@ -2968,9 +2973,11 @@ # even if they haven't explicitly been requested yet (if they've # never been used by hg, they won't ever have been written, even if # they're a subset of another kind of cache that *has* been used). + dpt = repository.CACHE_BRANCHMAP_DETECT_PURE_TOPO in caches + for filt in repoview.filtertable.keys(): filtered = self.filtered(filt) - self._branchcaches.update_disk(filtered) + self._branchcaches.update_disk(filtered, detect_pure_topo=dpt) # flush all possibly delayed write. self._branchcaches.write_dirty(self)