2015-09-25 23:45:08 +03:00
|
|
|
# perftweaks.py
|
|
|
|
#
|
|
|
|
# Copyright 2015 Facebook, Inc.
|
|
|
|
#
|
|
|
|
# This software may be used and distributed according to the terms of the
|
|
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
"""extension for tweaking Mercurial features to improve performance."""
|
|
|
|
|
2015-11-25 02:18:39 +03:00
|
|
|
from mercurial import branchmap, merge, revlog, scmutil, tags
|
2015-09-25 23:45:08 +03:00
|
|
|
from mercurial.extensions import wrapcommand, wrapfunction
|
|
|
|
from mercurial.i18n import _
|
2015-11-09 22:33:38 +03:00
|
|
|
from mercurial.node import nullid, nullrev
|
2015-09-25 23:45:08 +03:00
|
|
|
import os
|
|
|
|
|
|
|
|
testedwith = 'internal'
|
|
|
|
|
|
|
|
def extsetup(ui):
|
|
|
|
wrapfunction(tags, '_readtagcache', _readtagcache)
|
perftweaks: disable case collision checking
Summary:
Case collision detection makes every hg update on OSX take an extra 3 seconds.
For rebasing a stack of commits, that's an extra 3 seconds per commit. This is a
rare enough situation that let's just disable the check. Then we can catch such
issues in a commit hook or as a post-commit hook audit.
Test Plan:
Ran hg update, it was 3s faster than before.
Tested a case conflict, it ended up modifying both files. Hopefully this would
be caught in code review, though we could also do it via pre-commit hook.
```
$ touch a && hg add a
$ hg commit -m 'lower case a'
$ hg up .^
$ touch A && hg add A
$ hg commit -m 'upper case A'
$ hg rebase -d . -s {lower case a commit}
$ hg show
diff --git a/fbandroid/A b/fbandroid/A
--- a/fbandroid/A
+++ b/fbandroid/A
@@ -1,1 +1,1 @@
-A
+a
diff --git a/fbandroid/a b/fbandroid/a
new file mode 100644
--- /dev/null
+++ b/fbandroid/a
@@ -0,0 +1,1 @@
+a
```
Reviewers: pyd, mpm, #sourcecontrol, rmcelroy
Reviewed By: rmcelroy
Subscribers: rmcelroy
Differential Revision: https://phabricator.fb.com/D2486617
Signature: t1:2486617:1443483300:f2520c09ce9eb6d3b8e1c1a35b175f0441b10630
2015-09-28 23:54:21 +03:00
|
|
|
wrapfunction(merge, '_checkcollision', _checkcollision)
|
2015-11-09 22:33:38 +03:00
|
|
|
wrapfunction(branchmap.branchcache, 'update', _branchmapupdate)
|
2015-11-25 02:18:39 +03:00
|
|
|
if ui.configbool('perftweaks', 'preferdeltas'):
|
|
|
|
wrapfunction(revlog.revlog, '_isgooddelta', _isgooddelta)
|
2015-09-25 23:45:08 +03:00
|
|
|
|
|
|
|
def _readtagcache(orig, ui, repo):
|
perftweaks: disable case collision checking
Summary:
Case collision detection makes every hg update on OSX take an extra 3 seconds.
For rebasing a stack of commits, that's an extra 3 seconds per commit. This is a
rare enough situation that let's just disable the check. Then we can catch such
issues in a commit hook or as a post-commit hook audit.
Test Plan:
Ran hg update, it was 3s faster than before.
Tested a case conflict, it ended up modifying both files. Hopefully this would
be caught in code review, though we could also do it via pre-commit hook.
```
$ touch a && hg add a
$ hg commit -m 'lower case a'
$ hg up .^
$ touch A && hg add A
$ hg commit -m 'upper case A'
$ hg rebase -d . -s {lower case a commit}
$ hg show
diff --git a/fbandroid/A b/fbandroid/A
--- a/fbandroid/A
+++ b/fbandroid/A
@@ -1,1 +1,1 @@
-A
+a
diff --git a/fbandroid/a b/fbandroid/a
new file mode 100644
--- /dev/null
+++ b/fbandroid/a
@@ -0,0 +1,1 @@
+a
```
Reviewers: pyd, mpm, #sourcecontrol, rmcelroy
Reviewed By: rmcelroy
Subscribers: rmcelroy
Differential Revision: https://phabricator.fb.com/D2486617
Signature: t1:2486617:1443483300:f2520c09ce9eb6d3b8e1c1a35b175f0441b10630
2015-09-28 23:54:21 +03:00
|
|
|
"""Disables reading tags if the repo is known to not contain any."""
|
2015-09-25 23:45:08 +03:00
|
|
|
if ui.configbool('perftweaks', 'disabletags'):
|
|
|
|
return (None, None, None, {}, False)
|
|
|
|
|
|
|
|
return orig(ui, repo)
|
perftweaks: disable case collision checking
Summary:
Case collision detection makes every hg update on OSX take an extra 3 seconds.
For rebasing a stack of commits, that's an extra 3 seconds per commit. This is a
rare enough situation that let's just disable the check. Then we can catch such
issues in a commit hook or as a post-commit hook audit.
Test Plan:
Ran hg update, it was 3s faster than before.
Tested a case conflict, it ended up modifying both files. Hopefully this would
be caught in code review, though we could also do it via pre-commit hook.
```
$ touch a && hg add a
$ hg commit -m 'lower case a'
$ hg up .^
$ touch A && hg add A
$ hg commit -m 'upper case A'
$ hg rebase -d . -s {lower case a commit}
$ hg show
diff --git a/fbandroid/A b/fbandroid/A
--- a/fbandroid/A
+++ b/fbandroid/A
@@ -1,1 +1,1 @@
-A
+a
diff --git a/fbandroid/a b/fbandroid/a
new file mode 100644
--- /dev/null
+++ b/fbandroid/a
@@ -0,0 +1,1 @@
+a
```
Reviewers: pyd, mpm, #sourcecontrol, rmcelroy
Reviewed By: rmcelroy
Subscribers: rmcelroy
Differential Revision: https://phabricator.fb.com/D2486617
Signature: t1:2486617:1443483300:f2520c09ce9eb6d3b8e1c1a35b175f0441b10630
2015-09-28 23:54:21 +03:00
|
|
|
|
|
|
|
def _checkcollision(orig, repo, wmf, actions):
|
|
|
|
"""Disables case collision checking since it is known to be very slow."""
|
2015-10-07 22:29:56 +03:00
|
|
|
if repo.ui.configbool('perftweaks', 'disablecasecheck'):
|
perftweaks: disable case collision checking
Summary:
Case collision detection makes every hg update on OSX take an extra 3 seconds.
For rebasing a stack of commits, that's an extra 3 seconds per commit. This is a
rare enough situation that let's just disable the check. Then we can catch such
issues in a commit hook or as a post-commit hook audit.
Test Plan:
Ran hg update, it was 3s faster than before.
Tested a case conflict, it ended up modifying both files. Hopefully this would
be caught in code review, though we could also do it via pre-commit hook.
```
$ touch a && hg add a
$ hg commit -m 'lower case a'
$ hg up .^
$ touch A && hg add A
$ hg commit -m 'upper case A'
$ hg rebase -d . -s {lower case a commit}
$ hg show
diff --git a/fbandroid/A b/fbandroid/A
--- a/fbandroid/A
+++ b/fbandroid/A
@@ -1,1 +1,1 @@
-A
+a
diff --git a/fbandroid/a b/fbandroid/a
new file mode 100644
--- /dev/null
+++ b/fbandroid/a
@@ -0,0 +1,1 @@
+a
```
Reviewers: pyd, mpm, #sourcecontrol, rmcelroy
Reviewed By: rmcelroy
Subscribers: rmcelroy
Differential Revision: https://phabricator.fb.com/D2486617
Signature: t1:2486617:1443483300:f2520c09ce9eb6d3b8e1c1a35b175f0441b10630
2015-09-28 23:54:21 +03:00
|
|
|
return
|
|
|
|
orig(repo, wmf, actions)
|
2015-11-09 22:33:38 +03:00
|
|
|
|
|
|
|
def _branchmapupdate(orig, self, repo, revgen):
|
|
|
|
if not repo.ui.configbool('perftweaks', 'disablebranchcache'):
|
|
|
|
return orig(self, repo, revgen)
|
|
|
|
|
|
|
|
cl = repo.changelog
|
|
|
|
|
|
|
|
# Since we have no branches, the default branch heads are equal to
|
|
|
|
# cl.headrevs().
|
|
|
|
branchheads = sorted(cl.headrevs())
|
|
|
|
|
|
|
|
self['default'] = [cl.node(rev) for rev in branchheads]
|
|
|
|
tiprev = branchheads[-1]
|
|
|
|
if tiprev > self.tiprev:
|
|
|
|
self.tipnode = cl.node(tiprev)
|
|
|
|
self.tiprev = tiprev
|
|
|
|
|
|
|
|
# Copy and paste from branchmap.branchcache.update()
|
|
|
|
if not self.validfor(repo):
|
|
|
|
# cache key are not valid anymore
|
|
|
|
self.tipnode = nullid
|
|
|
|
self.tiprev = nullrev
|
|
|
|
for heads in self.values():
|
|
|
|
tiprev = max(cl.rev(node) for node in heads)
|
|
|
|
if tiprev > self.tiprev:
|
|
|
|
self.tipnode = cl.node(tiprev)
|
|
|
|
self.tiprev = tiprev
|
|
|
|
self.filteredhash = scmutil.filteredhash(repo, self.tiprev)
|
|
|
|
repo.ui.log('branchcache', 'perftweaks updated %s branch cache\n',
|
|
|
|
repo.filtername)
|
2015-11-25 02:18:39 +03:00
|
|
|
|
|
|
|
def _isgooddelta(orig, self, d, textlen):
|
|
|
|
"""Returns True if the given delta is good. Good means that it is within
|
|
|
|
the disk span, disk size, and chain length bounds that we know to be
|
|
|
|
performant."""
|
|
|
|
if d is None:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# - 'dist' is the distance from the base revision -- bounding it limits
|
|
|
|
# the amount of I/O we need to do.
|
|
|
|
# - 'compresseddeltalen' is the sum of the total size of deltas we need
|
|
|
|
# to apply -- bounding it limits the amount of CPU we consume.
|
|
|
|
dist, l, data, base, chainbase, chainlen, compresseddeltalen = d
|
|
|
|
|
|
|
|
# Our criteria:
|
|
|
|
# 1. the delta is not larger than the full text
|
|
|
|
# 2. the delta chain cumulative size is not greater than twice the fulltext
|
|
|
|
# 3. The chain length is less than the maximum
|
|
|
|
#
|
|
|
|
# This differs from upstream Mercurial's criteria. They prevent the total
|
|
|
|
# ondisk span from chain base to rev from being greater than 4x the full
|
|
|
|
# text len. This isn't good enough in our world since if we have 10+
|
|
|
|
# branches going on at once, we can easily exceed the 4x limit and cause
|
|
|
|
# full texts to be written over and over again.
|
|
|
|
if (l > textlen or compresseddeltalen > textlen * 2 or
|
|
|
|
(self._maxchainlen and chainlen > self._maxchainlen)):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|