remotenames: avoid updating "selectivepullaccessedbookmarks" if unnecessary

Summary:
I encountered a 19s `hg sl` run where 13s were spent on
`remotenames.updateaccessedbookmarks` (8 times).

{F225347899}

The filesystem is unusually slow since the it's nearly full. However, the
updates are not really necessary since I'm not accessing more remote names.
Accessing one bookmark via smartlog rewrites the entire accessed file, which is
O(N^2) and undesirable.

Improve it by skipping writing if nothing has changed. In the future we might
want to optimize it further by:
- Only update (and do ui.log) "accessedbookmarks" at most once per command.
- Potentially drop the "accessedbookmarks" tracking by using "remotenames"
  directly - everything in "remotenames" is accessed.

Reviewed By: markbt

Differential Revision: D19191528

fbshipit-source-id: 46635d4e5c9d0034ace9cdafc1f42a4512aa8774
This commit is contained in:
Jun Wu 2019-12-20 08:57:46 -08:00 committed by Facebook Github Bot
parent 82df66ffe9
commit e41e214a01

View File

@ -284,11 +284,24 @@ def updateaccessedbookmarks(repo, remotepath, bookmarks):
if not _trackaccessedbookmarks(repo.ui):
return
# Are bookmarks already marked as accessed?
existing = set(
name
for _node, _nametype, oldremote, name in repo._accessedbookmarks
if oldremote == remotepath
)
newdata = set(bookmarks)
if existing.issuperset(newdata):
# If so, then skip updating the accessed file.
# Note: we ignore the "node" portion of the data since it's not
# actually used.
return
vfs = repo.sharedvfs
totalaccessednames = 0
with lockmod.lock(vfs, _selectivepullaccessedbookmarkslock):
knownbooks = set(_readremotenamesfrom(vfs, _selectivepullaccessedbookmarks))
knownbooks = _readremotenamesfrom(vfs, _selectivepullaccessedbookmarks)
with vfs(_selectivepullaccessedbookmarks, "w", atomictemp=True) as f:
newbookmarks = {}
@ -312,6 +325,10 @@ def updateaccessedbookmarks(repo, remotepath, bookmarks):
totalaccessednames += 1
_writesingleremotename(f, remotepath, "bookmarks", rname, node)
repo._accessedbookmarks = list(
_readremotenamesfrom(repo.sharedvfs, _selectivepullaccessedbookmarks)
)
# log the number of accessed bookmarks currently tracked
repo.ui.log("accessedremotenames", accessedremotenames_totalnum=totalaccessednames)
@ -841,6 +858,9 @@ def reposetup(ui, repo):
return
repo._remotenames = remotenames(repo)
repo._accessedbookmarks = list(
_readremotenamesfrom(repo.sharedvfs, _selectivepullaccessedbookmarks)
)
def _tracking(ui):