Anton Shestakov <engored@ya.ru>, Sat, 23 May 2015 17:10:09 +0800
bench: add (mark, cache) index for faster min/max value search in viewer
bench.py
Permissions: -rwxr-xr-x
from argparse import ArgumentParser from collections import OrderedDict from settings import DBPATH, HG, LOCKFILE, TESTHGREPO, TESTREPO, rel ('blame', 'hg blame README'), ('grepall', 'hg grep "version" --all README'), ('grepallf', 'hg grep "version" --all --follow README'), ('diff', 'hg diff -r "tip~100:tip" README'), ('diffg', 'hg diff -r "tip~100:tip" --git README'), ('stcp', 'hg status --copies README'), ('logfile', 'hg log README'), ('logfilecp', 'hg log --copies README'), ('log1000', 'hg log -l1000') parser = ArgumentParser(description='Benchmark revisions and put results in the db.') group = parser.add_mutually_exclusive_group() group.add_argument('revsets', metavar='REVSET', default=('last(all(), 120)',), nargs='*', help='update these revisions') group.add_argument('--auto', metavar='MAXREVS', type=int, help='guess revisions, up to MAXREVS') parser.add_argument('--retry', action='store_true', help='try and reduce existing timings') def test(mark, mintime=1.0, mintries=3, dropcache=True): cmd = [rel(TESTHGREPO, 'hg'), '-R', TESTREPO] cmd += ['blame', rel(TESTREPO, 'README')] cmd += ['grep', '--all', 'version', rel(TESTREPO, 'README')] cmd += ['grep', '--all', '--follow', 'version', rel(TESTREPO, 'README')] cmd += ['status', '--copies', rel(TESTREPO, 'README')] cmd += ['diff', '-r', 'tip~100:tip', rel(TESTREPO, 'README')] cmd += ['diff', '-r', 'tip~100:tip', '--git', rel(TESTREPO, 'README')] cmd += ['log', rel(TESTREPO, 'README')] elif mark == 'logfilecp': cmd += ['log', '--copies', rel(TESTREPO, 'README')] while sum(results) < mintime or len(results) < mintries: shutil.rmtree(rel(TESTREPO, '.hg', 'cache'), ignore_errors=True) subprocess.check_output(cmd) except subprocess.CalledProcessError: results.append(time.time() - start) cmd = [HG, 'log', '-R', TESTHGREPO, '-T', '{node}\n'] output = subprocess.check_output(cmd) """ Pick one continuous span of nodes that still need testing. """ cmd = [HG, 'log', '-R', TESTHGREPO, '-T', '{node}\n', '-r', 'sort(all(), rev)'] output = subprocess.check_output(cmd) conn = sqlite3.connect(DBPATH) while len(todo) < maxrevs: count = conn.execute('SELECT COUNT(*) FROM results WHERE node = ?', (node,)).fetchone()[0] if count < len(MARKS) * len(('without cache', 'with cache')): def guessspikes(maxrevs): cmd = [HG, 'log', '-R', TESTHGREPO, '-T', '{node}\n', '-r', 'sort(all(), -rev)'] output = subprocess.check_output(cmd) conn = sqlite3.connect(DBPATH) 'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?', (mark, False)).fetchone() 'SELECT MIN(time), MAX(time) FROM results WHERE mark = ? AND cache = ?', 'SELECT mark, time, cache FROM results WHERE node = ?', for mark, t, cache in resultsq: results.setdefault(node, {}).setdefault(mark, [None, None]) results[node][mark][0] = t results[node][mark][1] = t for i in range(1, len(nodes) - 1): for cache in (False, True): eps = abs(results[node1][mark][cache] - results[node3][mark][cache]) delta = results[node2][mark][cache] - results[node1][mark][cache] l = limits[mark][2:4] if cache else limits[mark][0:2] if delta > eps * 10 and delta > (l[1] - l[0]) * 0.1: except (KeyError, TypeError): subprocess.check_output(['make', '--directory', TESTHGREPO, 'clean'], stderr=subprocess.STDOUT) subprocess.check_output([HG, 'update', '-R', TESTHGREPO, '--clean', node], stderr=subprocess.STDOUT) subprocess.check_output(['make', '--directory', TESTHGREPO, 'local'], stderr=subprocess.STDOUT) conn = sqlite3.connect(DBPATH) 'CREATE TABLE IF NOT EXISTS results (' ' node CHAR(40) NOT NULL,' ' mark VARCHAR(40) NOT NULL,' 'CREATE INDEX IF NOT EXISTS idx_results_node ON results (node)') 'CREATE INDEX IF NOT EXISTS idx_results_mark_cache ON results (mark, cache)') def dbupdate(revsets, retry=False): conn = sqlite3.connect(DBPATH) nodes = getnodes(revsets) for i, node in enumerate(nodes, 1): for cache in (False, True): 'SELECT time FROM results WHERE node = ? AND mark = ? AND cache = ?', (node, mark, cache)).fetchall() oldtime = old[0][0] if old else None if oldtime is not None and not retry: time = test(mark, dropcache=not cache) logging.info('%05d/%05d %s %s %s', i, len(nodes), node, mark, time) 'INSERT INTO results (node, mark, time, cache) VALUES (?, ?, ?, ?)', (node, mark, time, cache)) 'UPDATE results SET time = ? WHERE node = ? AND mark = ? AND cache = ?', (time, node, mark, cache)) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL return os.fdopen(os.open(LOCKFILE, flags), 'w') if e.errno == errno.EEXIST: logging.error('cannot lock data directory') args.revsets = guessspikes(args.auto) args.revsets = guessnew(args.auto) dbupdate(args.revsets, args.retry) if __name__ == '__main__': logging.getLogger().setLevel(logging.INFO) args = parser.parse_args()