view tests/test-git-export.t @ 16120:47ee41fcf42b

largefiles: optimize update speed by only updating changed largefiles Historically, during 'hg update', every largefile in the working copy was hashed (which is a very expensive operation on big files) and any largefiles that did not have a hash that matched their standin were updated. This patch optimizes 'hg update' by keeping track of what standins have changed between the old and new revisions, and only updating the largefiles that have changed. This saves a lot of time by avoiding the unecessary calculation of a list of sha1 hashes for big files. With this patch, the time 'hg update' takes to complete is a function of how many largefiles need to be updated and what their size is. Performance tests on a repository with about 80 largefiles ranging from a few MB to about 97 MB are shown below. The tests show how long it takes to run 'hg update' with no changes actually being updated. Mercurial 2.1 release: $ time hg update 0 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 0 largefiles updated, 0 removed real 0m10.045s user 0m9.367s sys 0m0.674s With this patch: $ time hg update 0 files updated, 0 files merged, 0 files removed, 0 files unresolved real 0m0.965s user 0m0.845s sys 0m0.115s The same repsoitory, without the largefiles extension enabled: $ time hg update 0 files updated, 0 files merged, 0 files removed, 0 files unresolved real 0m0.799s user 0m0.684s sys 0m0.111s So before the patch, 'hg update' with no changes was approximately 9.25s slower with largefiles enabled. With this patch, it is approximately 0.165s slower.
author Na'Tosha Bard <natosha@unity3d.com>
date Mon, 13 Feb 2012 18:37:07 +0100
parents db0340f4b507
children 4f795f5fbb0b
line wrap: on
line source

  $ "$TESTDIR/hghave" execbit || exit 80

  $ hg init
  $ echo start > start
  $ hg ci -Amstart
  adding start

New file:

  $ echo new > new
  $ hg ci -Amnew
  adding new
  $ hg diff --git -r 0
  diff --git a/new b/new
  new file mode 100644
  --- /dev/null
  +++ b/new
  @@ -0,0 +1,1 @@
  +new

Copy:

  $ hg cp new copy
  $ hg ci -mcopy
  $ hg diff --git -r 1:tip
  diff --git a/new b/copy
  copy from new
  copy to copy

Rename:

  $ hg mv copy rename
  $ hg ci -mrename
  $ hg diff --git -r 2:tip
  diff --git a/copy b/rename
  rename from copy
  rename to rename

Delete:

  $ hg rm rename
  $ hg ci -mdelete
  $ hg diff --git -r 3:tip
  diff --git a/rename b/rename
  deleted file mode 100644
  --- a/rename
  +++ /dev/null
  @@ -1,1 +0,0 @@
  -new

  $ cat > src <<EOF
  > 1
  > 2
  > 3
  > 4
  > 5
  > EOF
  $ hg ci -Amsrc
  adding src

chmod 644:

  $ chmod +x src
  $ hg ci -munexec
  $ hg diff --git -r 5:tip
  diff --git a/src b/src
  old mode 100644
  new mode 100755

Rename+mod+chmod:

  $ hg mv src dst
  $ chmod -x dst
  $ echo a >> dst
  $ hg ci -mrenamemod
  $ hg diff --git -r 6:tip
  diff --git a/src b/dst
  old mode 100755
  new mode 100644
  rename from src
  rename to dst
  --- a/src
  +++ b/dst
  @@ -3,3 +3,4 @@
   3
   4
   5
  +a

Nonexistent in tip+chmod:

  $ hg diff --git -r 5:6
  diff --git a/src b/src
  old mode 100644
  new mode 100755

Binary diff:

  $ cp $TESTDIR/binfile.bin .
  $ hg add binfile.bin
  $ hg diff --git > b.diff
  $ cat b.diff
  diff --git a/binfile.bin b/binfile.bin
  new file mode 100644
  index 0000000000000000000000000000000000000000..37ba3d1c6f17137d9c5f5776fa040caf5fe73ff9
  GIT binary patch
  literal 593
  zc$@)I0<QguP)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM00009a7bBm000XU
  z000XU0RWnu7ytkO2XskIMF-Uh9TW;VpMjwv0005-Nkl<ZD9@FWPs=e;7{<>W$NUkd
  zX$nnYLt$-$V!?uy+1V%`z&Eh=ah|duER<4|QWhju3gb^nF*8iYobxWG-qqXl=2~5M
  z*IoDB)sG^CfNuoBmqLTVU^<;@nwHP!1wrWd`{(mHo6VNXWtyh{alzqmsH*yYzpvLT
  zLdY<T=ks|woh-`&01!ej#(xbV1f|pI*=%;d-%F*E*X#ZH`4I%6SS+$EJDE&ct=8po
  ziN#{?_j|kD%Cd|oiqds`xm@;oJ-^?NG3Gdqrs?5u*zI;{nogxsx~^|Fn^Y?Gdc6<;
  zfMJ+iF1J`LMx&A2?dEwNW8ClebzPTbIh{@$hS6*`kH@1d%Lo7fA#}N1)oN7`gm$~V
  z+wDx#)OFqMcE{s!JN0-xhG8ItAjVkJwEcb`3WWlJfU2r?;Pd%dmR+q@mSri5q9_W-
  zaR2~ECX?B2w+zELozC0s*6Z~|QG^f{3I#<`?)Q7U-JZ|q5W;9Q8i_=pBuSzunx=U;
  z9C)5jBoYw9^?EHyQl(M}1OlQcCX>lXB*ODN003Z&P17_@)3Pi=i0wb04<W?v-u}7K
  zXmmQA+wDgE!qR9o8jr`%=ab_&uh(l?R=r;Tjiqon91I2-hIu?57~@*4h7h9uORK#=
  fQItJW-{SoTm)8|5##k|m00000NkvXXu0mjf{mKw4
  

Import binary diff:

  $ hg revert binfile.bin
  $ rm binfile.bin
  $ hg import -mfoo b.diff
  applying b.diff
  $ cmp binfile.bin $TESTDIR/binfile.bin

Rename binary file:

  $ hg mv binfile.bin renamed.bin
  $ hg diff --git
  diff --git a/binfile.bin b/renamed.bin
  rename from binfile.bin
  rename to renamed.bin

Diff across many revisions:

  $ hg mv dst dst2
  $ hg ci -m 'mv dst dst2'

  $ echo >> start
  $ hg ci -m 'change start'

  $ hg revert -r -2 start
  $ hg mv dst2 dst3
  $ hg ci -m 'mv dst2 dst3; revert start'

  $ hg diff --git -r 9:11
  diff --git a/dst2 b/dst3
  rename from dst2
  rename to dst3

Reversed:

  $ hg diff --git -r 11:9
  diff --git a/dst3 b/dst2
  rename from dst3
  rename to dst2


  $ echo a >> foo
  $ hg add foo
  $ hg ci -m 'add foo'
  $ echo b >> foo
  $ hg ci -m 'change foo'
  $ hg mv foo bar
  $ hg ci -m 'mv foo bar'
  $ echo c >> bar
  $ hg ci -m 'change bar'

File created before r1 and renamed before r2:

  $ hg diff --git -r -3:-1
  diff --git a/foo b/bar
  rename from foo
  rename to bar
  --- a/foo
  +++ b/bar
  @@ -1,2 +1,3 @@
   a
   b
  +c

Reversed:

  $ hg diff --git -r -1:-3
  diff --git a/bar b/foo
  rename from bar
  rename to foo
  --- a/bar
  +++ b/foo
  @@ -1,3 +1,2 @@
   a
   b
  -c

File created in r1 and renamed before r2:

  $ hg diff --git -r -4:-1
  diff --git a/foo b/bar
  rename from foo
  rename to bar
  --- a/foo
  +++ b/bar
  @@ -1,1 +1,3 @@
   a
  +b
  +c

Reversed:

  $ hg diff --git -r -1:-4
  diff --git a/bar b/foo
  rename from bar
  rename to foo
  --- a/bar
  +++ b/foo
  @@ -1,3 +1,1 @@
   a
  -b
  -c

File created after r1 and renamed before r2:

  $ hg diff --git -r -5:-1
  diff --git a/bar b/bar
  new file mode 100644
  --- /dev/null
  +++ b/bar
  @@ -0,0 +1,3 @@
  +a
  +b
  +c

Reversed:

  $ hg diff --git -r -1:-5
  diff --git a/bar b/bar
  deleted file mode 100644
  --- a/bar
  +++ /dev/null
  @@ -1,3 +0,0 @@
  -a
  -b
  -c


Comparing with the working dir:

  $ echo >> start
  $ hg ci -m 'change start again'

  $ echo > created
  $ hg add created
  $ hg ci -m 'add created'

  $ hg mv created created2
  $ hg ci -m 'mv created created2'

  $ hg mv created2 created3

There's a copy in the working dir:

  $ hg diff --git
  diff --git a/created2 b/created3
  rename from created2
  rename to created3

There's another copy between the original rev and the wd:

  $ hg diff --git -r -2
  diff --git a/created b/created3
  rename from created
  rename to created3

The source of the copy was created after the original rev:

  $ hg diff --git -r -3
  diff --git a/created3 b/created3
  new file mode 100644
  --- /dev/null
  +++ b/created3
  @@ -0,0 +1,1 @@
  +
  $ hg ci -m 'mv created2 created3'


  $ echo > brand-new
  $ hg add brand-new
  $ hg ci -m 'add brand-new'
  $ hg mv brand-new brand-new2

Created in parent of wd; renamed in the wd:

  $ hg diff --git
  diff --git a/brand-new b/brand-new2
  rename from brand-new
  rename to brand-new2

Created between r1 and parent of wd; renamed in the wd:

  $ hg diff --git -r -2
  diff --git a/brand-new2 b/brand-new2
  new file mode 100644
  --- /dev/null
  +++ b/brand-new2
  @@ -0,0 +1,1 @@
  +
  $ hg ci -m 'mv brand-new brand-new2'

One file is copied to many destinations and removed:

  $ hg cp brand-new2 brand-new3
  $ hg mv brand-new2 brand-new3-2
  $ hg ci -m 'multiple renames/copies'
  $ hg diff --git -r -2 -r -1
  diff --git a/brand-new2 b/brand-new3
  rename from brand-new2
  rename to brand-new3
  diff --git a/brand-new2 b/brand-new3-2
  copy from brand-new2
  copy to brand-new3-2

Reversed:

  $ hg diff --git -r -1 -r -2
  diff --git a/brand-new3 b/brand-new2
  rename from brand-new3
  rename to brand-new2
  diff --git a/brand-new3-2 b/brand-new3-2
  deleted file mode 100644
  --- a/brand-new3-2
  +++ /dev/null
  @@ -1,1 +0,0 @@
  -

There should be a trailing TAB if there are spaces in the file name:

  $ echo foo > 'with spaces'
  $ hg add 'with spaces'
  $ hg diff --git
  diff --git a/with spaces b/with spaces
  new file mode 100644
  --- /dev/null
  +++ b/with spaces	
  @@ -0,0 +1,1 @@
  +foo
  $ hg ci -m 'add filename with spaces'