sparse: move bits of perftweaks into sparse directly

Summary: No point in tweaking it externally if we can just add relevant stuff.

Reviewed By: phillco

Differential Revision: D10335080

fbshipit-source-id: 47c009bf820f8f41f586b714181e82bea88dfa49
This commit is contained in:
Kostia Balytskyi 2018-10-16 14:19:25 -07:00 committed by Facebook Github Bot
parent 86f07601f7
commit 6d171b17c6
5 changed files with 132 additions and 136 deletions

View File

@ -7,19 +7,10 @@
"""extension for tweaking Mercurial features to improve performance.
::
[perftweaks]
# Whether to use faster hidden cache. It has faster cache hash calculation
# which only check stat of a few files inside store/ directory.
fasthiddencache = False
[perftweaks]
# Whether to advertise usage of the sparse profiles when the checkout size
# is very large.
largecheckouthint = False
# The number of files in the checkout that constitute a "large checkout".
largecheckoutcount = 0
"""
import errno
@ -29,12 +20,10 @@ from mercurial import (
branchmap,
dispatch,
extensions,
hintutil,
localrepo,
merge,
namespaces,
phases,
registrar,
scmutil,
tags,
util,
@ -46,12 +35,6 @@ from mercurial.node import bin
testedwith = "ships-with-fb-hgext"
configtable = {}
configitem = registrar.configitem(configtable)
configitem("perftweaks", "largecheckouthint", default=False)
configitem("perftweaks", "largecheckoutcount", default=0)
def extsetup(ui):
# developer config: extensions.clindex
@ -64,8 +47,6 @@ def extsetup(ui):
wrapfunction(branchmap, "replacecache", _branchmapreplacecache)
wrapfunction(branchmap, "updatecache", _branchmapupdatecache)
wrapfunction(dispatch, "runcommand", _trackdirstatesizes)
wrapfunction(dispatch, "runcommand", _tracksparseprofiles)
wrapfunction(merge, "update", _trackupdatesize)
try:
@ -349,64 +330,6 @@ def _savepreloadrevs(repo, name, revs):
pass
hint = registrar.hint()
@hint("perftweaks-largecheckout")
def hintexplainverbose(dirstatesize, repo):
return (
_(
"Your repository checkout has %s files which makes Many mercurial "
"commands slower. Learn how to make it smaller at "
"https://fburl.com/hgsparse"
)
% dirstatesize
)
def sparseenabled():
sparse = None
try:
sparse = extensions.find("sparse")
except KeyError:
return False
if sparse:
return True
def _trackdirstatesizes(runcommand, lui, repo, *args):
res = runcommand(lui, repo, *args)
if repo is not None and repo.local():
dirstate = repo.dirstate
dirstatesize = None
try:
# Eden and flat dirstate.
dirstatesize = len(dirstate._map._map)
except AttributeError:
# Treestate and treedirstate.
dirstatesize = len(dirstate._map)
if dirstatesize is not None:
lui.log("dirstate_size", "", dirstate_size=dirstatesize)
if (
repo.ui.configbool("perftweaks", "largecheckouthint")
and dirstatesize
>= repo.ui.configint("perftweaks", "largecheckoutcount")
# eden has the sparse extension disabled
and sparseenabled()
):
hintutil.trigger("perftweaks-largecheckout", dirstatesize, repo)
return res
def _tracksparseprofiles(runcommand, lui, repo, *args):
res = runcommand(lui, repo, *args)
if repo is not None and repo.local():
if util.safehasattr(repo, "getactiveprofiles"):
profiles = repo.getactiveprofiles()
lui.log("sparse_profiles", "", active_profiles=",".join(sorted(profiles)))
return res
def _trackupdatesize(orig, repo, node, branchmerge, *args, **kwargs):
if not branchmerge:
try:

View File

@ -99,6 +99,15 @@ reflected in the UI.
profile_directory = tools/scm/sparse
It is not set by default.
It is also possible to show hints where dirstate size is too large.
[sparse]
# Whether to advertise usage of the sparse profiles when the checkout size
# is very large.
largecheckouthint = False
# The number of files in the checkout that constitute a "large checkout".
largecheckoutcount = 0
"""
from __future__ import division
@ -114,6 +123,7 @@ from mercurial import (
commands,
context,
dirstate,
dispatch,
error,
extensions,
hg,
@ -137,17 +147,26 @@ from mercurial.thirdparty import attr
cmdtable = {}
command = registrar.command(cmdtable)
configtable = {}
configitem = registrar.configitem(configtable)
testedwith = "ships-with-fb-hgext"
cwdrealtivepatkinds = ("glob", "relpath")
configitem("sparse", "largecheckouthint", default=False)
configitem("sparse", "largecheckoutcount", default=0)
def uisetup(ui):
_setupupdates(ui)
_setupcommit(ui)
def extsetup(ui):
extensions.wrapfunction(dispatch, "runcommand", _trackdirstatesizes)
extensions.wrapfunction(dispatch, "runcommand", _tracksparseprofiles)
_setupclone(ui)
_setuplog(ui)
_setupadd(ui)
@ -217,6 +236,10 @@ def _checksparse(repo):
raise error.Abort(_("this is not a sparse repository"))
def _hassparse(repo):
return "eden" not in repo.requirements and util.safehasattr(repo, "sparsematch")
def _setupupdates(ui):
def _calculateupdates(
orig, repo, wctx, mctx, ancestors, branchmerge, *arg, **kwargs
@ -376,6 +399,43 @@ def _setuplog(ui):
extensions.wrapfunction(cmdutil, "_logrevs", _logrevs)
def _tracksparseprofiles(runcommand, lui, repo, *args):
res = runcommand(lui, repo, *args)
if repo is not None and repo.local():
# config override is used to prevent duplicated "profile not found"
# messages. This code flow is purely for hints/reporting, it makes
# no sense for it to warn user about the profiles for the second time
with repo.ui.configoverride({("sparse", "missingwarning"): False}):
if util.safehasattr(repo, "getactiveprofiles"):
profiles = repo.getactiveprofiles()
lui.log(
"sparse_profiles", "", active_profiles=",".join(sorted(profiles))
)
return res
def _trackdirstatesizes(runcommand, lui, repo, *args):
res = runcommand(lui, repo, *args)
if repo is not None and repo.local():
dirstate = repo.dirstate
dirstatesize = None
try:
# Eden and flat dirstate.
dirstatesize = len(dirstate._map._map)
except AttributeError:
# Treestate and treedirstate.
dirstatesize = len(dirstate._map)
if dirstatesize is not None:
lui.log("dirstate_size", "", dirstate_size=dirstatesize)
if (
repo.ui.configbool("sparse", "largecheckouthint")
and dirstatesize >= repo.ui.configint("sparse", "largecheckoutcount")
and _hassparse(repo)
):
hintutil.trigger("sparse-largecheckout", dirstatesize, repo)
return res
def _clonesparsecmd(orig, ui, repo, *args, **opts):
include_pat = opts.get("include")
exclude_pat = opts.get("exclude")
@ -1248,6 +1308,18 @@ def _profilesizeinfo(ui, repo, *config, **kwargs):
hint = registrar.hint()
@hint("sparse-largecheckout")
def hintlargecheckout(dirstatesize, repo):
return (
_(
"Your repository checkout has %s files which makes Many mercurial "
"commands slower. Learn how to make it smaller at "
"https://fburl.com/hgsparse"
)
% dirstatesize
)
@hint("sparse-explain-verbose")
def hintexplainverbose(*profiles):
return _(

View File

@ -159,62 +159,3 @@ Test file permissions
drwxrw[sx]r-x.? [0-9]+ .* \. (re)
drwxrw[sx]r-x.? [0-9]+ .* \.\. (re)
-rw-rw-r--.? 1 .* branchheads-served (re)
Test logging the dirsize and sparse profiles
Set up the sampling extension and set a log file, then do a repo status.
We need to disable the SCM_SAMPLING_FILEPATH env var because arcanist may set it!
$ LOGDIR=`pwd`/logs
$ mkdir $LOGDIR
$ cat >> $HGRCPATH << EOF
> [sampling]
> key.dirstate_size=dirstate_size
> key.sparse_profiles=sparse_profiles
> filepath = $LOGDIR/samplingpath.txt
> [perftweaks]
> largecheckouthint=True
> largecheckoutcount=1
> [extensions]
> sampling=
> EOF
$ unset SCM_SAMPLING_FILEPATH
$ hg status
>>> import json
>>> with open("$LOGDIR/samplingpath.txt") as f:
... data = f.read()
>>> for record in data.strip("\0").split("\0"):
... parsedrecord = json.loads(record)
... print('{0}: {1}'.format(parsedrecord['category'],
... parsedrecord['data']['dirstate_size']))
dirstate_size: 1
$ cat >> $HGRCPATH << EOF
> [extensions]
> sparse=$TESTDIR/../hgext/sparse.py
> EOF
$ cat >> profile_base << EOF
> [include]
> a
> EOF
$ cat >> profile_extended << EOF
> %include profile_base
> EOF
$ hg add profile_base profile_extended
hint[perftweaks-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack perftweaks-largecheckout' to silence these hints
$ hg ci -m 'adding sparse profiles'
hint[perftweaks-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack perftweaks-largecheckout' to silence these hints
$ hg sparse --enable-profile profile_extended
hint[perftweaks-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack perftweaks-largecheckout' to silence these hints
>>> import json
>>> with open("$LOGDIR/samplingpath.txt") as f:
... data = f.read()
>>> for record in data.strip("\0").split("\0"):
... parsedrecord = json.loads(record)
... if parsedrecord['category'] == 'sparse_profiles':
... print('active_profiles:', parsedrecord['data']['active_profiles'])
active_profiles:
active_profiles:
active_profiles: profile_base,profile_extended

View File

@ -23,6 +23,7 @@ Test integration with simplecache for profile reads
$ hg sparse --enable-profile .hgsparse
$ hg status --debug
got value for key sparseprofile:.hgsparse:52fe6c0958d7d08df53bdf7ee62a261abb7f599e:v1 from local
got value for key sparseprofile:.hgsparse:52fe6c0958d7d08df53bdf7ee62a261abb7f599e:v1 from local
#if fsmonitor
Test fsmonitor integration (if available)

View File

@ -454,3 +454,62 @@ manifest and some are not.
n 644 0 * included (glob)
a 0 -1 * includedadded (glob)
Test logging the dirsize and sparse profiles
Set up the sampling extension and set a log file, then do a repo status.
We need to disable the SCM_SAMPLING_FILEPATH env var because arcanist may set it!
$ touch a && hg add a
$ unset SCM_SAMPLING_FILEPATH
$ hg ci -m "add some new files"
$ LOGDIR=`pwd`/logs
$ mkdir $LOGDIR
$ cat >> $HGRCPATH << EOF
> [sampling]
> key.dirstate_size=dirstate_size
> key.sparse_profiles=sparse_profiles
> filepath = $LOGDIR/samplingpath.txt
> [extensions]
> sampling=
> EOF
$ rm -f $LOGDIR/samplingpath.txt
$ hg status
>>> import json
>>> with open("$LOGDIR/samplingpath.txt") as f:
... data = f.read()
>>> for record in data.strip("\0").split("\0"):
... parsedrecord = json.loads(record)
... if parsedrecord['category'] == 'dirstate_size':
... print('{0}: {1}'.format(parsedrecord['category'],
... parsedrecord['data']['dirstate_size']))
dirstate_size: 3
$ cat >> profile_base << EOF
> [include]
> a
> EOF
$ cat >> profile_extended << EOF
> %include profile_base
> EOF
$ cat >> $HGRCPATH << EOF
> [sparse]
> largecheckouthint=True
> largecheckoutcount=1
> EOF
$ hg add profile_base profile_extended
hint[sparse-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack sparse-largecheckout' to silence these hints
$ hg ci -m 'adding sparse profiles'
hint[sparse-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack sparse-largecheckout' to silence these hints
$ rm -f $LOGDIR/samplingpath.txt
$ hg sparse --enable-profile profile_extended
hint[sparse-largecheckout]: Your repository checkout has * files which makes Many mercurial commands slower. Learn how to make it smaller at https://fburl.com/hgsparse (glob)
hint[hint-ack]: use 'hg hint --ack sparse-largecheckout' to silence these hints
>>> import json
>>> with open("$LOGDIR/samplingpath.txt") as f:
... data = f.read()
>>> for record in data.strip("\0").split("\0"):
... parsedrecord = json.loads(record)
... if parsedrecord['category'] == 'sparse_profiles':
... print('active_profiles:', parsedrecord['data']['active_profiles'])
active_profiles: profile_base,profile_extended