Matt Harbison <matt_harbison@yahoo.com> [Sat, 21 Nov 2020 16:55:07 -0500] rev 46021
extensions: gracefully warn when doing min version check with no local version
After doing a `make clean`, I started getting cryptic failures to import
extensions with the `minimumhgversion` attribute on py3:
*** failed to import extension evolve: '>' not supported between instances of 'int' and 'NoneType'
*** failed to import extension topic: '>' not supported between instances of 'int' and 'NoneType'
This now handles the `(None, None)` tuple before comparing, and disables the
extension with the same friendly message as in py2.
Differential Revision: https://phab.mercurial-scm.org/D9363
Yuya Nishihara <yuya@tcha.org> [Sat, 28 Nov 2020 11:15:54 +0900] rev 46020
diff: do not concatenate immutable bytes while building a/b bodies (
issue6445)
Use bytearray instead. I don't know what's changed since Python 2, but bytes
concatenation is 100x slow on Python 3.
% python2.7 -m timeit -s "s = b''" "for i in range(10000): s += b'line'"
1000 loops, best of 3: 321 usec per loop
% python3.9 -m timeit -s "s = b''" "for i in range(10000): s += b'line'"
5 loops, best of 5: 39.2 msec per loop
Benchmark using tailwind.css (measuring the fast path, a is empty):
% HGRCPATH=/dev/null python2.7 ./hg log -R /tmp/
issue6445 -p --time \
--color=always --config diff.word-diff=true >/dev/null
(prev) time: real 1.580 secs (user 1.560+0.000 sys 0.020+0.000)
(this) time: real 1.610 secs (user 1.570+0.000 sys 0.030+0.000)
% HGRCPATH=/dev/null python3.9 ./hg log -R /tmp/
issue6445 -p --time \
--color=always --config diff.word-diff=true >/dev/null
(prev) time: real 114.500 secs (user 114.460+0.000 sys 0.030+0.000)
(this) time: real 2.180 secs (user 2.140+0.000 sys 0.040+0.000)
Benchmark using random tabular text data (not the fast path):
% dd if=/dev/urandom bs=1k count=1000 | hexdump -v -e '16/1 "%3u," "\n"' > ttf
% hg ci -ma
% dd if=/dev/urandom bs=1k count=1000 | hexdump -v -e '16/1 "%3u," "\n"' > ttf
% hg ci -mb
% HGRCPATH=/dev/null python2.7 ./hg log -R /tmp/
issue6445 -p --time \
--color=always --config diff.word-diff=true >/dev/null
(prev) time: real 3.240 secs (user 3.040+0.000 sys 0.200+0.000
(this) time: real 3.230 secs (user 3.070+0.000 sys 0.160+0.000)
% HGRCPATH=/dev/null python3.9 ./hg log -R /tmp/
issue6445 -p --time \
--color=always --config diff.word-diff=true >/dev/null
(prev) time: real 44.130 secs (user 43.850+0.000 sys 0.270+0.000)
(this) time: real 4.170 secs (user 3.850+0.000 sys 0.310+0.000)
Augie Fackler <augie@google.com> [Tue, 01 Dec 2020 01:18:21 -0500] rev 46019
procutil: use rapply(tonativestr, ...) to preserve lists when they come in
This was broken when script was a list instead of a string. I caught this
with an internal extension at Google, and I'm not really sure why it wasn't
caught in any kind of CI.
Differential Revision: https://phab.mercurial-scm.org/D9471
Kyle Lippincott <spectral@google.com> [Wed, 02 Dec 2020 12:33:51 -0800] rev 46018
statprof: separate functions and "line", assume 4 digit line numbers
Previously, the profile output looked like this (I've removed many lines that
are mostly inconsequential):
```
| 100.0% 0.02s hg: <module> line 43: dispatch.run()
| 100.0% 0.02s dispatch.py: run line 115: status = dispatch(req)
| 100.0% 0.02s dispatch.py: _runcatchfunc line 432: return _dispatch(req)
\ 50.0% 0.01s dispatch.py: _dispatch line 1228: return runcommand(
| 50.0% 0.01s dispatch.py: runcommand line 883: ret = _runcommand(ui, optio...
| 50.0% 0.01s dispatch.py: _runcommand line 1240: return cmdfunc()
| 50.0% 0.01s localrepo.py: __getitem__ line 1670: quick_access = self._quick_...
| 50.0% 0.01s localrepo.py: _quick_access_changeidline 1650: return self._quick_access_c...
| 50.0% 0.01s localrepo.py: __get__ line 179: return getattr(unfi, self.n...
| 50.0% 0.01s util.py: __get__ line 1747: result = self.func(obj)
| 50.0% 0.01s localrepo.py: _quick_access_changeid_wcline 1611: cl = self.unfiltered().chan...
| 50.0% 0.01s localrepo.py: __get__ line 110: return super(_basefilecache...
| 50.0% 0.01s util.py: __getattribute__line 245: self.__spec__.loader.exec_m...
| 50.0% 0.01s <frozen importlib._bootstrap_external>: exec_moduleline 783:
| 50.0% 0.01s <frozen importlib._bootstrap>: _call_with_frames_removedline 219:
| 50.0% 0.01s changelog.py: <module> line 376: class changelog(revlog.revl...
| 50.0% 0.01s util.py: __getattribute__line 245: self.__spec__.loader.exec_m...
| 50.0% 0.01s <frozen importlib._bootstrap_external>: exec_moduleline 779:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: get_codeline 868:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: path_statsline 1012:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: _path_statline 87:
```
This has a few problems, though I'm only addressing some of them.
1. If the stuff before "line ###" is long, there's no separation between the
function name and the "line" string.
2. If the stuff before "line ###" is really long, there's excessive separation
between the "line" string and the line number.
3. We frequently have 4-digit line numbers, the code on the right wasn't
dynamically indented and ended up quite messy looking.
To solve these problems, I've added a ", " prefix before "line" iff it would
otherwise not have any separation such as spaces. I've added a 'max' so that we
never use a negative width (which is the cause of problem #2 above), and I've
added a default assumption of 4 digit line numbers (but again using a 'max' so
this shouldn't cause problems if we go beyond that.
With these changes, it now looks like this:
```
| 100.0% 0.02s hg: <module> line 43: dispatch.run()
| 100.0% 0.02s dispatch.py: run line 115: status = dispatch(req)
| 100.0% 0.02s dispatch.py: _runcatchfunc line 432: return _dispatch(req)
\ 50.0% 0.01s dispatch.py: _dispatch line 1228: return runcommand(
| 50.0% 0.01s dispatch.py: runcommand line 883: ret = _runcommand(ui, optio...
| 50.0% 0.01s dispatch.py: _runcommand line 1240: return cmdfunc()
| 50.0% 0.01s localrepo.py: __getitem__ line 1670: quick_access = self._quick_...
| 50.0% 0.01s localrepo.py: _quick_access_changeid, line 1650: return self._quick_access_c...
| 50.0% 0.01s localrepo.py: __get__ line 179: return getattr(unfi, self.n...
| 50.0% 0.01s util.py: __get__ line 1747: result = self.func(obj)
| 50.0% 0.01s localrepo.py: _quick_access_changeid_wc, line 1611: cl = self.unfiltered().chan...
| 50.0% 0.01s localrepo.py: __get__ line 110: return super(_basefilecache...
| 50.0% 0.01s util.py: __getattribute__, line 245: self.__spec__.loader.exec_m...
| 50.0% 0.01s <frozen importlib._bootstrap_external>: exec_module, line 783:
| 50.0% 0.01s <frozen importlib._bootstrap>: _call_with_frames_removed, line 219:
| 50.0% 0.01s changelog.py: <module> line 376: class changelog(revlog.revl...
| 50.0% 0.01s util.py: __getattribute__, line 245: self.__spec__.loader.exec_m...
| 50.0% 0.01s <frozen importlib._bootstrap_external>: exec_module, line 779:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: get_code, line 868:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: path_stats, line 1012:
| 50.0% 0.01s <frozen importlib._bootstrap_external>: _path_stat, line 87:
```
Differential Revision: https://phab.mercurial-scm.org/D9511
Kyle Lippincott <spectral@google.com> [Wed, 02 Dec 2020 15:38:05 -0800] rev 46017
statprof: fix off-by-one-line error in output
martinvonz claims they thought that this was intentional, but couldn't remember
the reasoning for it. I can't understand why it would be preferable, and I
didn't see anything in the comments in the file about why this would be useful,
so I'm hopefully not breaking anything by "fixing" it.
### Old output
```
| 100.0% 0.01s dispatch.py: run line 43: dispatch.run()
| 100.0% 0.01s dispatch.py: dispatch line 115: status = dispatch(req)
| 100.0% 0.01s dispatch.py: _runcatch line 266: ret = _runcatch(req) or 0
| 100.0% 0.01s dispatch.py: _callcatch line 442: return _callcatch(ui, _runc...
| 100.0% 0.01s scmutil.py: callcatch line 451: return scmutil.callcatch(ui...
| 100.0% 0.01s dispatch.py: _runcatchfunc line 155: return func()
| 100.0% 0.01s dispatch.py: _dispatch line 432: return _dispatch(req)
| 100.0% 0.01s hg.py: repository line 1179: repo = hg.repository(
| 100.0% 0.01s hg.py: _peerorrepo line 221: peer = _peerorrepo(
| 100.0% 0.01s util.py: __getattribute__ line 188: obj = _peerlookup(path).ins...
| 100.0% 0.01s localrepo.py: makelocalrepositoryline 3227: return makelocalrepository(...
| 100.0% 0.01s localrepo.py: __init__ line 683: return cls(
| 100.0% 0.01s util.py: __getattribute__ line 1262: self._extrafilterid = repov...
| 100.0% 0.01s <frozen importlib._bootstrap_external>: exec_moduleline 245: self.__spec__.loader.exec_m...
| 100.0% 0.01s <frozen importlib._bootstrap_external>: get_codeline 779:
| 100.0% 0.01s <frozen importlib._bootstrap_external>: path_statsline 868:
| 100.0% 0.01s <frozen importlib._bootstrap_external>: _path_statline 1012:
```
### New output
```
| 100.0% 0.01s hg: <module> line 43: dispatch.run()
| 100.0% 0.01s dispatch.py: run line 115: status = dispatch(req)
| 100.0% 0.01s dispatch.py: dispatch line 266: ret = _runcatch(req) or 0
| 100.0% 0.01s dispatch.py: _runcatch line 442: return _callcatch(ui, _runc...
| 100.0% 0.01s dispatch.py: _callcatch line 451: return scmutil.callcatch(ui...
| 100.0% 0.01s scmutil.py: callcatch line 155: return func()
| 100.0% 0.01s dispatch.py: _runcatchfunc line 432: return _dispatch(req)
| 100.0% 0.01s dispatch.py: _dispatch line 1179: repo = hg.repository(
| 100.0% 0.01s hg.py: repository line 221: peer = _peerorrepo(
| 100.0% 0.01s hg.py: _peerorrepo line 188: obj = _peerlookup(path).ins...
| 100.0% 0.01s localrepo.py: instance line 3227: return makelocalrepository(...
| 100.0% 0.01s localrepo.py: makelocalrepositoryline 683: return cls(
| 100.0% 0.01s localrepo.py: __init__ line 1262: self._extrafilterid = repov...
| 100.0% 0.01s util.py: __getattribute__ line 245: self.__spec__.loader.exec_m...
| 100.0% 0.01s <frozen importlib._bootstrap_external>: exec_moduleline 779:
| 100.0% 0.01s <frozen importlib._bootstrap_external>: get_codeline 868:
| 100.0% 0.01s <frozen importlib._bootstrap_external>: path_statsline 1012:
| 100.0% 0.01s <frozen importlib._bootstrap_external>: _path_statline 87:
```
Differential Revision: https://phab.mercurial-scm.org/D9510
Pierre-Yves David <pierre-yves.david@octobus.net> [Thu, 03 Dec 2020 08:09:56 +0100] rev 46016
phab-refresh: do not error out when the stack is empty
Actually, empty stack is easier to get than I expected (and harmless). When a
stack is publish, heptapod will detect the even, empty the stack (triggering CI)
and "forgetting" the branch afterward.
So we stop returning as error in this case.
Differential Revision: https://phab.mercurial-scm.org/D9513