diff -r 042ed354b9eb -r dcac24ec935b mercurial/commandserver.py --- a/mercurial/commandserver.py Wed Oct 31 22:19:03 2018 +0900 +++ b/mercurial/commandserver.py Wed Oct 31 22:43:08 2018 +0900 @@ -28,6 +28,7 @@ error, loggingutil, pycompat, + repocache, util, vfs as vfsmod, ) @@ -511,6 +512,11 @@ self._oldsigchldhandler = None self._workerpids = set() # updated by signal handler; do not iterate self._socketunlinked = None + # experimental config: cmdserver.max-repo-cache + maxlen = ui.configint(b'cmdserver', b'max-repo-cache') + if maxlen < 0: + raise error.Abort(_('negative max-repo-cache size not allowed')) + self._repoloader = repocache.repoloader(ui, maxlen) def init(self): self._sock = socket.socket(socket.AF_UNIX) @@ -525,6 +531,7 @@ o = signal.signal(signal.SIGCHLD, self._sigchldhandler) self._oldsigchldhandler = o self._socketunlinked = False + self._repoloader.start() def _unlinksocket(self): if not self._socketunlinked: @@ -537,6 +544,7 @@ self._mainipc.close() self._workeripc.close() self._unlinksocket() + self._repoloader.stop() # don't kill child processes as they have active clients, just wait self._reapworkers(0) @@ -590,6 +598,10 @@ return raise + # Future improvement: On Python 3.7, maybe gc.freeze() can be used + # to prevent COW memory from being touched by GC. + # https://instagram-engineering.com/ + # copy-on-write-friendly-python-garbage-collection-ad6ed5233ddf pid = os.fork() if pid: try: @@ -622,8 +634,7 @@ if inst.args[0] == errno.EINTR: return raise - - self.ui.log(b'cmdserver', b'repository: %s\n', path) + self._repoloader.load(path) def _sigchldhandler(self, signal, frame): self._reapworkers(os.WNOHANG) @@ -671,3 +682,9 @@ repo.__class__ = unixcmdserverrepo repo._cmdserveripc = self._workeripc + + cachedrepo = self._repoloader.get(repo.root) + if cachedrepo is None: + return + repo.ui.log(b'repocache', b'repo from cache: %s\n', repo.root) + repocache.copycache(cachedrepo, repo)