|
| 1 | +""" |
| 2 | +Simple replacement for mbdirector package. |
| 3 | +Contains only the Benchmark and RunConfig classes needed for tests. |
| 4 | +""" |
| 5 | +import os |
| 6 | +import subprocess |
| 7 | +import logging |
| 8 | + |
| 9 | + |
| 10 | +class RunConfig(object): |
| 11 | + """Configuration for a benchmark run.""" |
| 12 | + next_id = 1 |
| 13 | + |
| 14 | + def __init__(self, base_results_dir, name, config, benchmark_config): |
| 15 | + self.id = RunConfig.next_id |
| 16 | + RunConfig.next_id += 1 |
| 17 | + |
| 18 | + self.redis_process_port = config.get('redis_process_port', 6379) |
| 19 | + |
| 20 | + mbconfig = config.get('memtier_benchmark', {}) |
| 21 | + mbconfig.update(benchmark_config) |
| 22 | + self.mb_binary = mbconfig.get('binary', 'memtier_benchmark') |
| 23 | + self.mb_threads = mbconfig.get('threads') |
| 24 | + self.mb_clients = mbconfig.get('clients') |
| 25 | + self.mb_pipeline = mbconfig.get('pipeline') |
| 26 | + self.mb_requests = mbconfig.get('requests') |
| 27 | + self.mb_test_time = mbconfig.get('test_time') |
| 28 | + self.explicit_connect_args = bool( |
| 29 | + mbconfig.get('explicit_connect_args')) |
| 30 | + |
| 31 | + self.results_dir = os.path.join(base_results_dir, |
| 32 | + '{:04}_{}'.format(self.id, name)) |
| 33 | + |
| 34 | + def __repr__(self): |
| 35 | + return '<RunConfig id={}>'.format(self.id) |
| 36 | + |
| 37 | + |
| 38 | +class Benchmark(object): |
| 39 | + """Benchmark runner for memtier_benchmark.""" |
| 40 | + |
| 41 | + def __init__(self, config, **kwargs): |
| 42 | + self.config = config |
| 43 | + self.binary = self.config.mb_binary |
| 44 | + self.name = kwargs['name'] |
| 45 | + |
| 46 | + # Configure |
| 47 | + self.args = [self.binary] |
| 48 | + if not self.config.explicit_connect_args: |
| 49 | + self.args += ['--server', '127.0.0.1', |
| 50 | + '--port', str(self.config.redis_process_port) |
| 51 | + ] |
| 52 | + self.args += ['--out-file', os.path.join(config.results_dir, |
| 53 | + 'mb.stdout'), |
| 54 | + '--json-out-file', os.path.join(config.results_dir, |
| 55 | + 'mb.json')] |
| 56 | + |
| 57 | + if self.config.mb_threads is not None: |
| 58 | + self.args += ['--threads', str(self.config.mb_threads)] |
| 59 | + if self.config.mb_clients is not None: |
| 60 | + self.args += ['--clients', str(self.config.mb_clients)] |
| 61 | + if self.config.mb_pipeline is not None: |
| 62 | + self.args += ['--pipeline', str(self.config.mb_pipeline)] |
| 63 | + if self.config.mb_requests is not None: |
| 64 | + self.args += ['--requests', str(self.config.mb_requests)] |
| 65 | + if self.config.mb_test_time is not None: |
| 66 | + self.args += ['--test-time', str(self.config.mb_test_time)] |
| 67 | + |
| 68 | + self.args += kwargs['args'] |
| 69 | + |
| 70 | + @classmethod |
| 71 | + def from_json(cls, config, json): |
| 72 | + return cls(config, **json) |
| 73 | + |
| 74 | + def write_file(self, name, data): |
| 75 | + with open(os.path.join(self.config.results_dir, name), 'wb') as outfile: |
| 76 | + outfile.write(data) |
| 77 | + |
| 78 | + def run(self): |
| 79 | + logging.debug(' Command: %s', ' '.join(self.args)) |
| 80 | + process = subprocess.Popen( |
| 81 | + stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 82 | + executable=self.binary, args=self.args) |
| 83 | + _stdout, _stderr = process.communicate() |
| 84 | + if _stderr: |
| 85 | + logging.debug(' >>> stderr <<<\n%s\n', _stderr) |
| 86 | + self.write_file('mb.stderr', _stderr) |
| 87 | + return process.wait() == 0 |
| 88 | + |
0 commit comments