Sat, 18 Feb 2017 17:23:43 -0800 smartset: use native set operations as fast paths
Jun Wu <quark@fb.com> [Sat, 18 Feb 2017 17:23:43 -0800] rev 31020
smartset: use native set operations as fast paths For set operations like "&" and "-", where we know both basesets have their sets ready, and the first set is sorted, use the native Python set operations as a fast path. Note: "+" is not optimized as that will break the ordering. This leads to noticeable improvements on performance: revset | before | after | delta ---------------------------------------------------------------- draft() & draft() & draft() & draft() | 776 | 477 | -39% draft() + draft() + draft() + draft() | 2849 | 2864 | draft() - draft() + draft() - draft() | 943 | 240 | -75% draft() - draft() - draft() - draft() | 557 | 197 | -64% (time measured in microseconds)
Sat, 18 Feb 2017 16:30:07 -0800 smartset: add some doctests
Jun Wu <quark@fb.com> [Sat, 18 Feb 2017 16:30:07 -0800] rev 31019
smartset: add some doctests Add doctests explaining the set / list behavior. This will make the following changes more confident.
Sat, 18 Feb 2017 00:55:20 -0800 obsolete: avoid using revset language to compute the obsolete revset
Jun Wu <quark@fb.com> [Sat, 18 Feb 2017 00:55:20 -0800] rev 31018
obsolete: avoid using revset language to compute the obsolete revset This is part of a refactoring that moves some phase query optimization from revset.py to phases.py. See previous patches for the motivation. Now we have APIs in phasecache to get the non-public set efficiently, let's use it directly instead of going through the "not public()" revset language in "obsolete()" computation. This patch was meaured using: for i in 'public()' 'not public()' 'draft()' 'not draft()'; do hg perfrevset "$i"; hg perfrevset "$i" --hidden; done and no noticeable (> 1%) performance difference was observed.
Sat, 18 Feb 2017 00:39:31 -0800 revset: use phasecache.getrevset
Jun Wu <quark@fb.com> [Sat, 18 Feb 2017 00:39:31 -0800] rev 31017
revset: use phasecache.getrevset This is part of a refactoring that moves some phase query optimization from revset.py to phases.py. See the previous patch for motivation. This patch changes revset code to use phasecache.getrevset so it no longer accesses the private field: _phasecache._phasesets directly. For performance impact, this patch was tested using the following query, on my hg-committed repo: for i in 'public()' 'not public()' 'draft()' 'not draft()'; do echo $i; hg perfrevset "$i"; hg perfrevset "$i" --hidden; done For the CPython implementation, most operations are unchanged (within +/- 1%), while "not public()" and "draft()" is noticeably faster on an unfiltered repo. It may be because the new code avoids a set copy if filteredrevs is empty. revset | public() | not public() | draft() | not draft() hidden | yes | no | yes | no | yes | no | yes | no ------------------------------------------------------------------ before | 19006 | 17352 | 239 | 286 | 180 | 228 | 7690 | 5745 after | 19137 | 17231 | 240 | 207 | 182 | 150 | 7687 | 5658 delta | | -38% | | -52% | (timed in microseconds) For the pure Python implementation, some operations are faster while "not draft()" is noticeably slower: revset | public() | not public() | draft() | not draft() hidden | yes | no | yes | no | yes | no | yes | no ------------------------------------------------------------------------ before | 18852 | 17183 | 17758 | 15921 | 17505 | 15973 | 41521 | 39822 after | 18924 | 17380 | 17558 | 14545 | 16727 | 13593 | 48356 | 43992 delta | | -9% | -5% | -15% | +16% | +10% That may be the different performance characters of generatorset vs. filteredset. The "not draft()" query could be optimized in this case where both "public" and "secret" are passed to "getrevsets" so it won't iterate the whole repo twice.
Fri, 17 Feb 2017 22:49:05 -0800 phases: add a getrevset method to phasecache
Jun Wu <quark@fb.com> [Fri, 17 Feb 2017 22:49:05 -0800] rev 31016
phases: add a getrevset method to phasecache This is part of a refactoring that moves some phase query optimization from revset.py to phases.py. The motivation behind this was chg repo preloading - to make the obsstore depend on less things (like the revset language). The refactoring also looks good by itself - phasecache does not expose its private field "_phasesets" via public methods and revset.py is accessing it in a hacky way. This patch adds a "getrevset" method, which takes multiple phases and returns a revset in an best-effort efficient way - for "public" phase, it returns a lazy generatorset; for "draft" and "secret", it returns efficient "baseset".
Fri, 17 Feb 2017 20:59:29 -0800 smartset: convert set to list lazily
Jun Wu <quark@fb.com> [Fri, 17 Feb 2017 20:59:29 -0800] rev 31015
smartset: convert set to list lazily If the caller only wants to construct a baseset via a set, and then do "__contains__" tests. It's unnecessary to initialize the list. Testing on my unfiltered hg-committed repo where len(draft()) is 2600, this patch shows about 6% improvement on set intensive queries: Before: $ for i in `seq 5`; hg perfrevset 'draft() & draft() & draft() & draft()' ! wall 0.001196 comb 0.000000 user 0.000000 sys 0.000000 (best of 2011) ! wall 0.001191 comb 0.000000 user 0.000000 sys 0.000000 (best of 2099) ! wall 0.001186 comb 0.010000 user 0.010000 sys 0.000000 (best of 1953) ! wall 0.001182 comb 0.000000 user 0.000000 sys 0.000000 (best of 2135) ! wall 0.001193 comb 0.000000 user 0.000000 sys 0.000000 (best of 2177) After: $ for i in `seq 5`; hg perfrevset 'draft() & draft() & draft() & draft()' ! wall 0.001128 comb 0.000000 user 0.000000 sys 0.000000 (best of 2247) ! wall 0.001119 comb 0.000000 user 0.000000 sys 0.000000 (best of 2317) ! wall 0.001115 comb 0.000000 user 0.000000 sys 0.000000 (best of 2244) ! wall 0.001131 comb 0.000000 user 0.000000 sys 0.000000 (best of 2093) ! wall 0.001124 comb 0.000000 user 0.000000 sys 0.000000 (best of 2134) It could have bigger impact on larger sets in theory.
Thu, 16 Feb 2017 11:34:50 -0500 ui: construct _keepalnum list in a python3-friendly way
Augie Fackler <augie@google.com> [Thu, 16 Feb 2017 11:34:50 -0500] rev 31014
ui: construct _keepalnum list in a python3-friendly way It'll be more expensive, but it preserves the behavior.
Mon, 13 Feb 2017 17:03:14 -0800 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com> [Mon, 13 Feb 2017 17:03:14 -0800] rev 31013
match: making visitdir() deal with non-recursive entries Primarily as an optimization to avoid recursing into directories that will never have a match inside, this classifies each matcher pattern's root as recursive or non-recursive (erring on the side of keeping it recursive, which may lead to wasteful directory or manifest walks that yield no matches). I measured the performance of "rootfilesin" in two repos: - The Firefox repo with tree manifests, with "hg files -r . -I rootfilesin:browser". The browser directory contains about 3K files across 249 subdirectories. - A specific Google-internal directory which contains 75K files across 19K subdirectories, with "hg files -r . -I rootfilesin:REDACTED". I tested with both cold and warm disk caches. Cold cache was produced by running "sync; echo 3 > /proc/sys/vm/drop_caches". Warm cache was produced by re-running the same command a few times. These were the results: Cold cache Warm cache Before After Before After firefox 0m5.1s 0m2.18s 0m0.22s 0m0.14s google3 dir 2m3.9s 0m1.57s 0m8.12s 0m0.16s Certain extensions, notably narrowhg, can depend on this for correctness (not trying to recurse into directories for which it has no information).
Mon, 13 Feb 2017 15:39:29 -0800 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com> [Mon, 13 Feb 2017 15:39:29 -0800] rev 31012
match: adding support for matching files inside a directory This adds a new "rootfilesin" matcher type which matches files inside a directory, but not any subdirectories (so it matches non-recursively). This has the "root" prefix per foozy's plan for other matchers (rootglob, rootpath, cwdre, etc.).
Fri, 17 Feb 2017 01:21:15 -0800 runtests: add an IPv6 command line flag
Jun Wu <quark@fb.com> [Fri, 17 Feb 2017 01:21:15 -0800] rev 31011
runtests: add an IPv6 command line flag Now we have all IPv6 related issues fixed, add a command line flag so people could actually run tests with IPv6.
Thu, 16 Feb 2017 08:43:59 -0800 runtests: always set web.ipv6
Jun Wu <quark@fb.com> [Thu, 16 Feb 2017 08:43:59 -0800] rev 31010
runtests: always set web.ipv6 Previously, we only set web.ipv6 if IPv6 is used, but not on the IPv4 case. Since we already have set web.address, it makes sense to move "web.ipv6" out from "extra config options".
Thu, 16 Feb 2017 00:13:29 -0800 runtests: set web.address to localhost
Jun Wu <quark@fb.com> [Thu, 16 Feb 2017 00:13:29 -0800] rev 31009
runtests: set web.address to localhost Previously, "hg serve" will listen on "", which is not clear which interface it will actually listen on - it could listen on all interfaces (ex. 0.0.0.0 on IPv4). The run-tests.py script only checks "localhost" for available ports. So let's make it the same for "hg serve" by explicitly setting "web.address" to "localhost". This resolves some IPv6 EADDRINUSE errors.
Thu, 16 Feb 2017 09:38:52 -0800 tests: use LOCALIP
Jun Wu <quark@fb.com> [Thu, 16 Feb 2017 09:38:52 -0800] rev 31008
tests: use LOCALIP This patch replaces hardcoded 127.0.0.1 with $LOCALIP in all tests. Till now, the IPv6 series should make tests pass on common IPv6 systems where the local device has the address "::1" and the hostname "localhost" resolves to "::1".
Wed, 15 Feb 2017 23:24:03 -0800 dummyssh: use LOCALIP
Jun Wu <quark@fb.com> [Wed, 15 Feb 2017 23:24:03 -0800] rev 31007
dummyssh: use LOCALIP This patch replaces hard-coded 127.0.0.1 with $LOCALIP in dummyssh.
Thu, 16 Feb 2017 08:01:19 -0800 runtests: export LOCALIP
Jun Wu <quark@fb.com> [Thu, 16 Feb 2017 08:01:19 -0800] rev 31006
runtests: export LOCALIP Previously, tests hard-code local IP address as "127.0.0.1". That won't work for IPv6. This patch exports the $LOCALIP environment variable, which is set to "::1" if we decide to use IPv6.
Wed, 15 Feb 2017 22:53:45 -0800 tinyproxy: use IPv6 if HGIPV6 is set to 1
Jun Wu <quark@fb.com> [Wed, 15 Feb 2017 22:53:45 -0800] rev 31005
tinyproxy: use IPv6 if HGIPV6 is set to 1 This patch makes tinyproxy.py work in IPv6 mode if HGIPV6 is set to 1. This will make test-http-proxy.t pass on IPv6 machines.
Wed, 15 Feb 2017 21:09:00 -0800 dumbhttp: use IPv6 if HGIPV6 is set to 1
Jun Wu <quark@fb.com> [Wed, 15 Feb 2017 21:09:00 -0800] rev 31004
dumbhttp: use IPv6 if HGIPV6 is set to 1 This will fix flaky tests using dumbhttp. The patch was tested on gcc112.fsffrance.org using the following command: ./run-tests.py -j 40 --runs-per-test 120 test-bundle2-remote-changegroup.t
Wed, 15 Feb 2017 21:03:42 -0800 runtests: export HGIPV6 to hint test scripts whether to use IPv6
Jun Wu <quark@fb.com> [Wed, 15 Feb 2017 21:03:42 -0800] rev 31003
runtests: export HGIPV6 to hint test scripts whether to use IPv6 Previously, run-tests.py only exports HGPORT, and scripts in tests do not know if IPv6 should be used. And that breaks scripts like dumbhttp.py which always uses IPv4. This patch makes run-tests.py export HGIPV6, which can help test scripts like dumbhttp.py and tinyproxy.py to decide whether to use IPv6 or not.
Fri, 17 Feb 2017 00:59:09 -0800 runtests: prefer IPv4 to IPv6
Jun Wu <quark@fb.com> [Fri, 17 Feb 2017 00:59:09 -0800] rev 31002
runtests: prefer IPv4 to IPv6 To make IPv6 work, there are multiple areas that need to fix. Before they all get fixed, use IPv4 by default. This should fix tests caused on IPv6 systems.
Fri, 17 Feb 2017 11:08:36 +0100 doc: correct example concerning "hg purge" alias in man page "hgrc.5"
Rainer Woitok <Rainer.Woitok@Gmail.Com> [Fri, 17 Feb 2017 11:08:36 +0100] rev 31001
doc: correct example concerning "hg purge" alias in man page "hgrc.5" The "hg purge" alias as currently described in "hgrc.5" issues a possibly confusing error message like rm: missing operand Try 'rm --help' for more information. if no files are to be purged at all. This patch slightly modifies the example by adding a "-f" option to the "rm" command.
Mon, 06 Feb 2017 23:22:04 -0500 tests: prove that ignore works
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 23:22:04 -0500] rev 31000
tests: prove that ignore works
Mon, 06 Feb 2017 22:52:47 -0500 annotate: migrate to modern pager API
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 22:52:47 -0500] rev 30999
annotate: migrate to modern pager API
Mon, 06 Feb 2017 23:55:54 -0500 ui: add a debug print right before we start the pager
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 23:55:54 -0500] rev 30998
ui: add a debug print right before we start the pager This makes it easier to figure out why a command is getting paginated.
Mon, 06 Feb 2017 23:42:04 -0500 ui: respect historic pager.attend-$COMMAND=no
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 23:42:04 -0500] rev 30997
ui: respect historic pager.attend-$COMMAND=no I'm on the fence about this behavior, but the user's intent was pretty specific and it's not expensive to support this case.
Mon, 06 Feb 2017 23:45:30 -0500 tests: clean up a bunch of pager testing that is about to be invalidated
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 23:45:30 -0500] rev 30996
tests: clean up a bunch of pager testing that is about to be invalidated All this attend logic and potential bugs just no longer make sense to test.
Mon, 06 Feb 2017 23:21:45 -0500 ui: add ignore-single-command functionality
Augie Fackler <augie@google.com> [Mon, 06 Feb 2017 23:21:45 -0500] rev 30995
ui: add ignore-single-command functionality This closes the last feature gap other than the attend list from the extension. For now, I'm leaving the attend list in the extension, because I'm unsure it has merit in a world where commands have been updated to take advantage of the modern API.
Wed, 15 Feb 2017 17:48:03 -0500 ui: introduce neverpager() call
Augie Fackler <augie@google.com> [Wed, 15 Feb 2017 17:48:03 -0500] rev 30994
ui: introduce neverpager() call I'm about to add direct paging support to some commands, and as a result we need a way to communicate from the higher layers of dispatch that paging is explicitly disabled.
Wed, 15 Feb 2017 17:47:57 -0500 pager: move more behavior into core
Augie Fackler <augie@google.com> [Wed, 15 Feb 2017 17:47:57 -0500] rev 30993
pager: move more behavior into core This moves the global flag and the --pager=yes logic into core. Only functionality change is that users now always get a --pager flag and can enable the pager via the flag without the extension active. Moving the flag into core exposes a defect in the ro localization, which will have to be corrected later.
Wed, 15 Feb 2017 17:47:51 -0500 pager: move pager-initiating code into core
Augie Fackler <augie@google.com> [Wed, 15 Feb 2017 17:47:51 -0500] rev 30992
pager: move pager-initiating code into core No functionality change. A previous version of this API had a category argument on ui.pager(). As I migrated the commands in core, I couldn't come up with good enough consistency in any categorization scheme so I just scrapped the whole idea. It may be worth revisiting in the future.
Thu, 16 Feb 2017 10:33:59 -0800 test-logtoprocess: use cat to wait for outputs
Jun Wu <quark@fb.com> [Thu, 16 Feb 2017 10:33:59 -0800] rev 30991
test-logtoprocess: use cat to wait for outputs Commands started by logtoprocess are running asynchronously. To be able to test the output, we need to block and wait for the output. The patch uses "| cat" to wait for such "asynchronous" outputs, to make the test more reliable. I have also written a short notice at the top, hopefully people would be aware of the pitfall when changing the test.
(0) -30000 -10000 -3000 -1000 -300 -100 -50 -30 +30 +50 +100 +300 +1000 +3000 +10000 tip