view tests/test-fastannotate-protocol.t @ 44363:f7459da77f23

nodemap: introduce an option to use mmap to read the nodemap mapping The performance and memory benefit is much greater if we don't have to copy all the data in memory for each information. So we introduce an option (on by default) to read the data using mmap. This changeset is the last one definition the API for index support nodemap data. (they have to be able to use the mmaping). Below are some benchmark comparing the best we currently have in 5.3 with the final step of this series (using the persistent nodemap implementation in Rust). The benchmark run `hg perfindex` with various revset and the following variants: Before: * do not use the persistent nodemap * use the CPython implementation of the index for nodemap * use mmapping of the changelog index After: * use the MixedIndex Rust code, with the NodeTree object for nodemap access (still in review) * use the persistent nodemap data from disk * access the persistent nodemap data through mmap * use mmapping of the changelog index The persistent nodemap greatly speed up most operation on very large repositories. Some of the previously very fast lookup end up a bit slower because the persistent nodemap has to be setup. However the absolute slowdown is very small and won't matters in the big picture. Here are some numbers (in seconds) for the reference copy of mozilla-try: Revset Before After abs-change speedup -10000: 0.004622 0.005532 0.000910 × 0.83 -10: 0.000050 0.000132 0.000082 × 0.37 tip 0.000052 0.000085 0.000033 × 0.61 0 + (-10000:) 0.028222 0.005337 -0.022885 × 5.29 0 0.023521 0.000084 -0.023437 × 280.01 (-10000:) + 0 0.235539 0.005308 -0.230231 × 44.37 (-10:) + :9 0.232883 0.000180 -0.232703 ×1293.79 (-10000:) + (:99) 0.238735 0.005358 -0.233377 × 44.55 :99 + (-10000:) 0.317942 0.005593 -0.312349 × 56.84 :9 + (-10:) 0.313372 0.000179 -0.313193 ×1750.68 :9 0.316450 0.000143 -0.316307 ×2212.93 On smaller repositories, the cost of nodemap related operation is not as big, so the win is much more modest. Yet it helps shaving a handful of millisecond here and there. Here are some numbers (in seconds) for the reference copy of mercurial: Revset Before After abs-change speedup -10: 0.000065 0.000097 0.000032 × 0.67 tip 0.000063 0.000078 0.000015 × 0.80 0 0.000561 0.000079 -0.000482 × 7.10 -10000: 0.004609 0.003648 -0.000961 × 1.26 0 + (-10000:) 0.005023 0.003715 -0.001307 × 1.35 (-10:) + :9 0.002187 0.000108 -0.002079 ×20.25 (-10000:) + 0 0.006252 0.003716 -0.002536 × 1.68 (-10000:) + (:99) 0.006367 0.003707 -0.002660 × 1.71 :9 + (-10:) 0.003846 0.000110 -0.003736 ×34.96 :9 0.003854 0.000099 -0.003755 ×38.92 :99 + (-10000:) 0.007644 0.003778 -0.003866 × 2.02 Differential Revision: https://phab.mercurial-scm.org/D7894
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 11 Feb 2020 11:18:52 +0100
parents 7116fc614cfc
children 9c4204b7f3e4
line wrap: on
line source

  $ cat >> $HGRCPATH << EOF
  > [ui]
  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
  > [extensions]
  > fastannotate=
  > [fastannotate]
  > mainbranch=@
  > EOF

setup the server repo

  $ hg init repo-server
  $ cd repo-server
  $ cat >> .hg/hgrc << EOF
  > [fastannotate]
  > server=1
  > EOF
  $ for i in 1 2 3 4; do
  >   echo $i >> a
  >   hg commit -A -m $i a
  > done
  $ [ -d .hg/fastannotate ]
  [1]
  $ hg bookmark @
  $ cd ..

setup the local repo

  $ hg clone 'ssh://user@dummy/repo-server' repo-local -q
  $ cd repo-local
  $ cat >> .hg/hgrc << EOF
  > [fastannotate]
  > client=1
  > clientfetchthreshold=0
  > EOF
  $ [ -d .hg/fastannotate ]
  [1]
  $ hg fastannotate a --debug
  running * (glob)
  sending hello command
  sending between command
  remote: * (glob) (?)
  remote: capabilities: * (glob)
  remote: * (glob) (?)
  sending protocaps command
  fastannotate: requesting 1 files
  sending getannotate command
  fastannotate: writing 112 bytes to fastannotate/default/a.l
  fastannotate: writing 94 bytes to fastannotate/default/a.m
  fastannotate: a: using fast path (resolved fctx: True)
  0: 1
  1: 2
  2: 3
  3: 4

the cache could be reused and no download is necessary

  $ hg fastannotate a --debug
  fastannotate: a: using fast path (resolved fctx: True)
  0: 1
  1: 2
  2: 3
  3: 4

if the client agrees where the head of the master branch is, no re-download
happens even if the client has more commits

  $ echo 5 >> a
  $ hg commit -m 5
  $ hg bookmark -r 3 @ -f
  $ hg fastannotate a --debug
  0: 1
  1: 2
  2: 3
  3: 4
  4: 5

if the client has a different "@" (head of the master branch) and "@" is ahead
of the server, the server can detect things are unchanged and does not return
full contents (not that there is no "writing ... to fastannotate"), but the
client can also build things up on its own (causing diverge)

  $ hg bookmark -r 4 @ -f
  $ hg fastannotate a --debug
  running * (glob)
  sending hello command
  sending between command
  remote: * (glob) (?)
  remote: capabilities: * (glob)
  remote: * (glob) (?)
  sending protocaps command
  fastannotate: requesting 1 files
  sending getannotate command
  fastannotate: a: 1 new changesets in the main branch
  0: 1
  1: 2
  2: 3
  3: 4
  4: 5

if the client has a different "@" which is behind the server. no download is
necessary

  $ hg fastannotate a --debug --config fastannotate.mainbranch=2
  fastannotate: a: using fast path (resolved fctx: True)
  0: 1
  1: 2
  2: 3
  3: 4
  4: 5

define fastannotate on-disk paths

  $ p1=.hg/fastannotate/default
  $ p2=../repo-server/.hg/fastannotate/default

revert bookmark change so the client is behind the server

  $ hg bookmark -r 2 @ -f

in the "fctx" mode with the "annotate" command, the client also downloads the
cache. but not in the (default) "fastannotate" mode.

  $ rm $p1/a.l $p1/a.m
  $ hg annotate a --debug | grep 'fastannotate: writing'
  [1]
  $ hg annotate a --config fastannotate.modes=fctx --debug | grep 'fastannotate: writing' | sort
  fastannotate: writing 112 bytes to fastannotate/default/a.l
  fastannotate: writing 94 bytes to fastannotate/default/a.m

the fastannotate cache (built server-side, downloaded client-side) in two repos
have the same content (because the client downloads from the server)

  $ diff $p1/a.l $p2/a.l
  $ diff $p1/a.m $p2/a.m

in the "fctx" mode, the client could also build the cache locally

  $ hg annotate a --config fastannotate.modes=fctx --debug --config fastannotate.mainbranch=4 | grep fastannotate
  fastannotate: requesting 1 files
  fastannotate: a: 1 new changesets in the main branch

the server would rebuild broken cache automatically

  $ cp $p2/a.m $p2/a.m.bak
  $ echo BROKEN1 > $p1/a.m
  $ echo BROKEN2 > $p2/a.m
  $ hg fastannotate a --debug | grep 'fastannotate: writing' | sort
  fastannotate: writing 112 bytes to fastannotate/default/a.l
  fastannotate: writing 94 bytes to fastannotate/default/a.m
  $ diff $p1/a.m $p2/a.m
  $ diff $p2/a.m $p2/a.m.bak

use the "debugbuildannotatecache" command to build annotate cache

  $ rm -rf $p1 $p2
  $ hg --cwd ../repo-server debugbuildannotatecache a --debug
  fastannotate: a: 4 new changesets in the main branch
  $ hg --cwd ../repo-local debugbuildannotatecache a --debug
  running * (glob)
  sending hello command
  sending between command
  remote: * (glob) (?)
  remote: capabilities: * (glob)
  remote: * (glob) (?)
  sending protocaps command
  fastannotate: requesting 1 files
  sending getannotate command
  fastannotate: writing * (glob)
  fastannotate: writing * (glob)
  $ diff $p1/a.l $p2/a.l
  $ diff $p1/a.m $p2/a.m

with the clientfetchthreshold config option, the client can build up the cache
without downloading from the server

  $ rm -rf $p1
  $ hg fastannotate a --debug --config fastannotate.clientfetchthreshold=10
  fastannotate: a: 3 new changesets in the main branch
  0: 1
  1: 2
  2: 3
  3: 4
  4: 5

if the fastannotate directory is not writable, the fctx mode still works

  $ rm -rf $p1
  $ touch $p1
  $ hg annotate a --debug --traceback --config fastannotate.modes=fctx
  fastannotate: a: cache broken and deleted
  fastannotate: prefetch failed: * (glob)
  fastannotate: a: cache broken and deleted
  fastannotate: falling back to the vanilla annotate: * (glob)
  0: 1
  1: 2
  2: 3
  3: 4
  4: 5

with serverbuildondemand=False, the server will not build anything

  $ cat >> ../repo-server/.hg/hgrc <<EOF
  > [fastannotate]
  > serverbuildondemand=False
  > EOF
  $ rm -rf $p1 $p2
  $ hg fastannotate a --debug | grep 'fastannotate: writing'
  [1]