# HG changeset patch # User Philippe Pepiot <philippe.pepiot@logilab.fr> # Date 1522945588 -7200 # Thu Apr 05 18:26:28 2018 +0200 # Node ID 5f4d909fe90b5d91c0ff72102364ebed93fd34c2 # Parent 8ffc0035a0e7383332ddc3372dbc1a4760dc46dc Implement http exchange benchmarks By spawning a hg serve in setup() that serve repositories in repo/ It use a dynamic port allocation, used port is then read from "hg serve" stdout. diff --git a/benchmarks/basic_commands.py b/benchmarks/basic_commands.py --- a/benchmarks/basic_commands.py +++ b/benchmarks/basic_commands.py @@ -4,9 +4,18 @@ import os.path import time import timeit +import threading +import re import shutil import subprocess import stat +import sys + +if sys.version_info[0] == 2: + import Queue as queue +else: + import queue + from .utils import (BaseNChangesetsTestSuite, BaseTimeTestSuite, BaseTrackTestSuite, median, REPOS_DIR) @@ -121,11 +130,55 @@ self._execute("bundle", "--base", ":(-%d)" % (n+1), "/tmp/bundle.bundle") +class HgWeb(object): + + def __init__(self): + super(HgWeb, self).__init__() + self.queue = queue.Queue() + self.proc = None + self.thread = None + + def start(self, hgpath, environ): + config = os.path.abspath(os.path.join( + os.path.dirname(__file__), os.pardir, 'hgweb.config')) + self.proc = subprocess.Popen([ + hgpath, 'serve', '--cwd', REPOS_DIR, + '-a', 'localhost', '-p', '0', + '--webdir-conf', config], + env=environ, + stdout=subprocess.PIPE) + # we have to read output in a thread to avoid deadlocks + self.thread = threading.Thread( + target=self._enqueue, args=(self.queue, self.proc.stdout)) + self.thread.daemon = True + self.thread.start() + # wait the server to be started + statusline = self.queue.get() + if not statusline: + self.stop() + raise RuntimeError('hg serve has crashed') + return re.search(':(\d+)', statusline).groups()[0] + + @staticmethod + def _enqueue(queue, fd): + while True: + data = fd.readline() + if not data: + break + queue.put(data) + queue.put(None) + + def stop(self): + self.proc.kill() + self.proc.wait() + self.thread.join() + + class BaseExchangeTimeSuite(BaseTimeTestSuite): param_names = BaseTimeTestSuite.param_names + [ 'repo_type', 'strip', 'revset'] params = BaseTimeTestSuite.params + [ - ['local', 'ssh'], + ['local', 'ssh', 'http'], ['same', 'last(all(), 10)', 'last(all(), 100)', 'last(all(), 1000)'], [None, 'default']] timer = timeit.default_timer @@ -144,6 +197,12 @@ return [ '--remotecmd', os.path.abspath('hg_wrapper'), 'ssh://localhost/{}'.format(os.path.abspath(path))] + elif self.repo_type == 'http': + path = os.path.abspath(path) + repo_dir = os.path.abspath(REPOS_DIR) + assert path.startswith(REPOS_DIR), path + return ['http://localhost:{}/{}'.format( + self.hgport, path[len(repo_dir) + 1:])] else: raise NotImplementedError @@ -170,6 +229,15 @@ self.rev = None self.strip = strip self.repo_type = repo_type + if repo_type == 'http': + self._hgserve = HgWeb() + self.hgport = self._hgserve.start(self.hgpath, self.environ) + else: + self._hgserve = None + + def teardown(self, *args, **kwargs): + if self._hgserve is not None: + self._hgserve.stop() class ExchangeTimeSuite(BaseExchangeTimeSuite): @@ -184,7 +252,7 @@ class DiscoveryTimeSuite(BaseExchangeTimeSuite): # debugdiscovery does not support revset argument params = BaseTimeTestSuite.params + [ - ['local', 'ssh'], + ['local', 'ssh', 'http'], ['same', 'last(all(), 10)', 'last(all(), 100)', 'last(all(), 1000)'], [None]] @@ -228,7 +296,7 @@ class CloneTimeSuite(BaseExchangeTimeSuite): # skip other repos since they are too big - params = [['mercurial-2017'], ['local', 'ssh'], ['same'], [None, 'default']] + params = [['mercurial-2017'], ['local', 'ssh', 'http'], ['same'], [None, 'default']] timeout = 300 @@ -245,6 +313,7 @@ shutil.rmtree(self.tmp_clone_path, ignore_errors=True) def teardown(self, *args, **kwargs): + super(CloneTimeSuite, self).teardown(*args, **kwargs) shutil.rmtree(self.tmp_clone_path, ignore_errors=True) def time_clone(self, *args, **kwargs): diff --git a/hgweb.config b/hgweb.config new file mode 100644 --- /dev/null +++ b/hgweb.config @@ -0,0 +1,2 @@ +[paths] +/ = *