The recursive addremove operation occurs completely before the first subrepo is
committed. Only hg subrepos support the addremove operation at the moment- svn
and git subrepos will warn and abort the commit.
We use a `formatter` object in the perf extensions. This allow the use of
formatted output like json. To avoid adding logic to create a formatter and pass
it around to the timer function in every command, we add a `gettimer` function
in charge of returning a `timer` function as simple as before but embedding an
appropriate formatter.
This new `gettimer` function also return the formatter as it needs to be
explicitly closed at the end of the command.
example output:
$ hg --config ui.formatjson=True perfvolatilesets visible obsolete
[
{
"comb": 0.02,
"count": 126,
"sys": 0.0,
"title": "obsolete",
"user": 0.02,
"wall": 0.0199398994446
},
{
"comb": 0.02,
"count": 117,
"sys": 0.0,
"title": "visible",
"user": 0.02,
"wall": 0.0250301361084
}
]
With the new lazy revset implementation, we need to actually read all elements
to trigger all the computations. Otherwise a no-op if of course much faster than
the full work.
This is a step towards breaking an import cycle between revset and
repoview. Import cycles happened to work in Python 2 with implicit
relative imports, but breaks on Python 3 when we start using explicit
relative imports via 2to3 rewrite rules.
The annotate algorithm used a custom parents() function to try to reuse
filectx and filelogs. I simplified it a bit to rely more heavily on the
self.parents() which makes it work well with alternative filectx
implementations. I tested performance on a file with 5000+ revisions
but no renames, and on a file with 500 revisions repeating a series of
4 edits+renames and saw zero performance hit. In fact, it was reliably a
couple milliseconds faster now.
Added the perfannotate command to contrib/perf.py for future use.
This also makes the perfancestorset command use lazy membership testing. In a
linear repository with over 400,000 commits, without this patch, hg
perfancestorset takes 0.80 seconds no matter how far behind we're looking.
With this patch, hg perfancestorset -- X takes:
Rev X Time
-1 0.00s
-4000 0.01s
-20000 0.04s
-80000 0.17s
-200000 0.43s
-300000 0.69s
0 0.88s
Thus, for revisions close to tip, we're up to several orders of magnitude
faster. At 0 we're around 10% slower.
The new command, perfancestorset, takes an argument denoting which revset to
test the membership of.
Currently this runs through all the ancestors and converts them into a set.
The primary purpose of having this is to compare this approach, currently used
in several places, against the upcoming lazy approach.
When status needs to look at unknown files (e.g. when running hg status), it
needs to use a completely different algorithm than when it doesn't (e.g. when
running hg diff).
This makes sure that .hg/requires is observed and the correct kind of store
object is created. Otherwise we might mutilate our test repos when experimenting
with new repo formats.
Examples (all done with somewhat dated clones I found on my disk):
Netbeans (~120k entries in fncache):
$ hg perffncacheencode
! wall 4.338000 comb 4.336828 user 4.336828 sys 0.000000 (best of 3)
Openoffice (~77k entries in fncache)):
$ hg perffncacheencode
! wall 1.533000 comb 1.528810 user 1.528810 sys 0.000000 (best of 7)
Xen (~10k entries in fncache):
$ hg perffncacheencode
! wall 0.198000 comb 0.187201 user 0.187201 sys 0.000000 (best of 51)
Done on Windows 7 x64.
Accepting a variable number of arguments as the old API did is
deeply ugly, particularly as it means the API can't be extended
with new arguments. Partly as a result, we have at least three
different implementations of the same ancestors algorithm (!?).
Most callers were forced to call ancestors(*somelist), adding to
both inefficiency and ugliness.
This greatly speeds up node->rev lookups, with results that are
often user-perceptible: for instance, "hg --time log" of the node
associated with rev 1000 on a linux-2.6 repo improves from 0.3
seconds to 0.03. I have not found any instances of slowdowns.
The new perfnodelookup command in contrib/perf.py demonstrates the
speedup more dramatically, since it performs no I/O. For a single
lookup, the new code is about 40x faster.
These changes also prepare the ground for the possibility of further
improving the performance of prefix-based node lookups.
The most appropriate context is not always clearly defined. The obvious cases:
For working directory commands, we use None
For commands (eg annotate) with single revs, we use that revision
The less obvious cases:
For commands (eg status, diff) with a pair of revs, we use the second revision
For commands that take a range (like log), we use None