mercurial/repocache.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Sun, 17 Mar 2019 12:30:52 +0000
changeset 42019 5a1e621b8186
parent 40999 dcac24ec935b
child 43076 2372284d9457
permissions -rw-r--r--
perf: introduce a `perf.run-limits` options This options make it possible to configure the number of run that the extensions will perform. This is useful for automated benchmark or for performance measurement that need better accuracy.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40999
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
# repocache.py - in-memory repository cache for long-running services
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
#
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
# Copyright 2018 Yuya Nishihara <yuya@tcha.org>
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
#
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
from __future__ import absolute_import
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
import collections
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
import gc
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
import threading
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
from . import (
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
    error,
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
    hg,
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
    obsolete,
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
    scmutil,
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
    util,
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
class repoloader(object):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
    """Load repositories in background thread
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
    This is designed for a forking server. A cached repo cannot be obtained
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
    until the server fork()s a worker and the loader thread stops.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
    """
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    29
    def __init__(self, ui, maxlen):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    30
        self._ui = ui.copy()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
        self._cache = util.lrucachedict(max=maxlen)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
        # use deque and Event instead of Queue since deque can discard
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    33
        # old items to keep at most maxlen items.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    34
        self._inqueue = collections.deque(maxlen=maxlen)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    35
        self._accepting = False
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    36
        self._newentry = threading.Event()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    37
        self._thread = None
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    38
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
    def start(self):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
        assert not self._thread
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
        if self._inqueue.maxlen == 0:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
            # no need to spawn loader thread as the cache is disabled
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
            return
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    44
        self._accepting = True
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    45
        self._thread = threading.Thread(target=self._mainloop)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    46
        self._thread.start()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    48
    def stop(self):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    49
        if not self._thread:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
            return
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    51
        self._accepting = False
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
        self._newentry.set()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    53
        self._thread.join()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
        self._thread = None
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    55
        self._cache.clear()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    56
        self._inqueue.clear()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    57
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    58
    def load(self, path):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    59
        """Request to load the specified repository in background"""
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
        self._inqueue.append(path)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
        self._newentry.set()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
    def get(self, path):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
        """Return a cached repo if available
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    65
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    66
        This function must be called after fork(), where the loader thread
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    67
        is stopped. Otherwise, the returned repo might be updated by the
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    68
        loader thread.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    69
        """
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    70
        if self._thread and self._thread.is_alive():
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    71
            raise error.ProgrammingError(b'cannot obtain cached repo while '
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    72
                                         b'loader is active')
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
        return self._cache.peek(path, None)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    74
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    75
    def _mainloop(self):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    76
        while self._accepting:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    77
            # Avoid heavy GC after fork(), which would cancel the benefit of
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    78
            # COW. We assume that GIL is acquired while GC is underway in the
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
            # loader thread. If that isn't true, we might have to move
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    80
            # gc.collect() to the main thread so that fork() would never stop
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
            # the thread where GC is in progress.
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    82
            gc.collect()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    84
            self._newentry.wait()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    85
            while self._accepting:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
                self._newentry.clear()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
                try:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
                    path = self._inqueue.popleft()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    89
                except IndexError:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    90
                    break
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    91
                scmutil.callcatch(self._ui, lambda: self._load(path))
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    92
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    93
    def _load(self, path):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    94
        start = util.timer()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
        # TODO: repo should be recreated if storage configuration changed
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    96
        try:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    97
            # pop before loading so inconsistent state wouldn't be exposed
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    98
            repo = self._cache.pop(path)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    99
        except KeyError:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
            repo = hg.repository(self._ui, path).unfiltered()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   101
        _warmupcache(repo)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   102
        repo.ui.log(b'repocache', b'loaded repo into cache: %s (in %.3fs)\n',
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   103
                    path, util.timer() - start)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   104
        self._cache.insert(path, repo)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   105
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   106
# TODO: think about proper API of preloading cache
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   107
def _warmupcache(repo):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   108
    repo.invalidateall()
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   109
    repo.changelog
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   110
    repo.obsstore._all
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   111
    repo.obsstore.successors
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   112
    repo.obsstore.predecessors
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   113
    repo.obsstore.children
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   114
    for name in obsolete.cachefuncs:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   115
        obsolete.getrevs(repo, name)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   116
    repo._phasecache.loadphaserevs(repo)
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   117
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
# TODO: think about proper API of attaching preloaded attributes
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
def copycache(srcrepo, destrepo):
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
    """Copy cached attributes from srcrepo to destrepo"""
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
    destfilecache = destrepo._filecache
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
    srcfilecache = srcrepo._filecache
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
    if 'changelog' in srcfilecache:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
        destfilecache['changelog'] = ce = srcfilecache['changelog']
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
        ce.obj.opener = ce.obj._realopener = destrepo.svfs
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
    if 'obsstore' in srcfilecache:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
        destfilecache['obsstore'] = ce = srcfilecache['obsstore']
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
        ce.obj.svfs = destrepo.svfs
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
    if '_phasecache' in srcfilecache:
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   130
        destfilecache['_phasecache'] = ce = srcfilecache['_phasecache']
dcac24ec935b commandserver: preload repository in master server and reuse its file cache
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   131
        ce.obj.opener = destrepo.svfs