Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/revsetlang.py @ 51601:de5bf3fe0233
revset: stop serializing node when using "%ln"
Turning hundred of thousand of node from node to hex and back can be slow? what
about we stop doing it?
In many case were we are using node id we should be using revision id. However
this is not a good reason to have a stupidly slow implementation of "%ln".
This caught my attention again because the phase discovery during push make an
extensive use of "%ln" or huge set. In absolute, that phase discovery probably
should use "%ld" and need to improves its algorithmic complexity, but improving
"%ln" seems simple and long overdue. This greatly speeds up `hg push` on
repository with many drafts.
Here are some relevant poulpe benchmarks:
### data-env-vars.name = mozilla-try-2023-03-22-zstd-sparse-revlog
# benchmark.name = hg.command.push
# bin-env-vars.hg.flavor = default
# bin-env-vars.hg.py-re2-module = default
# benchmark.variants.explicit-rev = all-out-heads
# benchmark.variants.issue6528 = disabled
# benchmark.variants.protocol = ssh
# benchmark.variants.reuse-external-delta-parent = default
## benchmark.variants.revs = any-1-extra-rev
before: 44.235070
after: 20.416329 (-53.85%, -23.82)
## benchmark.variants.revs = any-100-extra-rev
before: 49.234697
after: 26.519829 (-46.14%, -22.71)
### benchmark.name = hg.command.bundle
# bin-env-vars.hg.flavor = default
# bin-env-vars.hg.py-re2-module = default
# benchmark.variants.revs = all
# benchmark.variants.type = none-streamv2
## data-env-vars.name = heptapod-public-2024-03-25-zstd-sparse-revlog
before: 10.138396
after: 7.750458 (-23.55%, -2.39)
## data-env-vars.name = mercurial-public-2024-03-22-zstd-sparse-revlog
before: 1.263859
after: 0.700229 (-44.60%, -0.56)
## data-env-vars.name = mozilla-try-2023-03-22-zstd-sparse-revlog
before: 399.484481
after: 346.5089 (-13.26%, -52.98)
## data-env-vars.name = pypy-2024-03-22-zstd-sparse-revlog
before: 4.540080
after: 3.401700 (-25.07%, -1.14)
## data-env-vars.name = tryton-public-2024-03-22-zstd-sparse-revlog
before: 2.975765
after: 1.870798 (-37.13%, -1.10)
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Fri, 05 Apr 2024 11:05:54 +0200 |
parents | 18c8c18993f0 |
children | f4733654f144 |
comparison
equal
deleted
inserted
replaced
51600:f610d705c3ca | 51601:de5bf3fe0233 |
---|---|
390 elif op == b'dagrangepost': | 390 elif op == b'dagrangepost': |
391 return _analyze(_build(b'descendants(_)', x[1])) | 391 return _analyze(_build(b'descendants(_)', x[1])) |
392 elif op == b'negate': | 392 elif op == b'negate': |
393 s = getstring(x[1], _(b"can't negate that")) | 393 s = getstring(x[1], _(b"can't negate that")) |
394 return _analyze((b'string', b'-' + s)) | 394 return _analyze((b'string', b'-' + s)) |
395 elif op in (b'string', b'symbol', b'smartset'): | 395 elif op in (b'string', b'symbol', b'smartset', b'nodeset'): |
396 return x | 396 return x |
397 elif op == b'rangeall': | 397 elif op == b'rangeall': |
398 return (op, None) | 398 return (op, None) |
399 elif op in {b'or', b'not', b'rangepre', b'rangepost', b'parentpost'}: | 399 elif op in {b'or', b'not', b'rangepre', b'rangepost', b'parentpost'}: |
400 return (op, _analyze(x[1])) | 400 return (op, _analyze(x[1])) |
439 def _optimize(x): | 439 def _optimize(x): |
440 if x is None: | 440 if x is None: |
441 return 0, x | 441 return 0, x |
442 | 442 |
443 op = x[0] | 443 op = x[0] |
444 if op in (b'string', b'symbol', b'smartset'): | 444 if op in (b'string', b'symbol', b'smartset', b'nodeset'): |
445 return 0.5, x # single revisions are small | 445 # single revisions are small, and set of already computed revision are assumed to be cheap. |
446 return 0.5, x | |
446 elif op == b'and': | 447 elif op == b'and': |
447 wa, ta = _optimize(x[1]) | 448 wa, ta = _optimize(x[1]) |
448 wb, tb = _optimize(x[2]) | 449 wb, tb = _optimize(x[2]) |
449 w = min(wa, wb) | 450 w = min(wa, wb) |
450 | 451 |
782 ret.append(arg) | 783 ret.append(arg) |
783 elif t == b'baseset': | 784 elif t == b'baseset': |
784 if isinstance(arg, set): | 785 if isinstance(arg, set): |
785 arg = sorted(arg) | 786 arg = sorted(arg) |
786 ret.append(_formatintlist(list(arg))) | 787 ret.append(_formatintlist(list(arg))) |
788 elif t == b'nodeset': | |
789 ret.append(_formatlistexp(list(arg), b"n")) | |
787 else: | 790 else: |
788 raise error.ProgrammingError(b"unknown revspec item type: %r" % t) | 791 raise error.ProgrammingError(b"unknown revspec item type: %r" % t) |
789 return b''.join(ret) | 792 return b''.join(ret) |
790 | 793 |
791 | 794 |
797 for t, arg in parsed: | 800 for t, arg in parsed: |
798 if t is None: | 801 if t is None: |
799 ret.append(arg) | 802 ret.append(arg) |
800 elif t == b'baseset': | 803 elif t == b'baseset': |
801 newtree = (b'smartset', smartset.baseset(arg)) | 804 newtree = (b'smartset', smartset.baseset(arg)) |
805 inputs.append(newtree) | |
806 ret.append(b"$") | |
807 elif t == b'nodeset': | |
808 newtree = (b'nodeset', arg) | |
802 inputs.append(newtree) | 809 inputs.append(newtree) |
803 ret.append(b"$") | 810 ret.append(b"$") |
804 else: | 811 else: |
805 raise error.ProgrammingError(b"unknown revspec item type: %r" % t) | 812 raise error.ProgrammingError(b"unknown revspec item type: %r" % t) |
806 expr = b''.join(ret) | 813 expr = b''.join(ret) |
861 # extra cost. If we are going to serialize it we better | 868 # extra cost. If we are going to serialize it we better |
862 # skip it. | 869 # skip it. |
863 ret.append((b'baseset', arg)) | 870 ret.append((b'baseset', arg)) |
864 pos += 1 | 871 pos += 1 |
865 continue | 872 continue |
873 elif islist and d == b'n' and arg: | |
874 # we cannot turn the node into revision yet, but not | |
875 # serializing them will same a lot of time for large set. | |
876 ret.append((b'nodeset', arg)) | |
877 pos += 1 | |
878 continue | |
866 try: | 879 try: |
867 ret.append((None, f(list(arg), d))) | 880 ret.append((None, f(list(arg), d))) |
868 except (TypeError, ValueError): | 881 except (TypeError, ValueError): |
869 raise error.ParseError(_(b'invalid argument for revspec')) | 882 raise error.ParseError(_(b'invalid argument for revspec')) |
870 else: | 883 else: |