perfkitbenchmarker/linux_packages/wrk.py (64 lines of code) (raw):

# Copyright 2015 PerfKitBenchmarker Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module containing wrk installation and cleanup functions. WRK is an extremely scalable HTTP benchmarking tool. https://github.com/wg/wrk """ import csv import posixpath from perfkitbenchmarker import linux_packages from perfkitbenchmarker import sample import six WRK_URL = 'https://github.com/wg/wrk/archive/4.0.1.tar.gz' WRK_DIR = posixpath.join(linux_packages.INSTALL_DIR, 'wrk') WRK_PATH = posixpath.join(WRK_DIR, 'wrk') # Rather than parse WRK's free text output, this script is used to generate a # CSV report _LUA_SCRIPT_NAME = 'wrk_latency.lua' _LUA_SCRIPT_PATH = posixpath.join(WRK_DIR, _LUA_SCRIPT_NAME) # Default socket / request timeout. _TIMEOUT = '10s' # WRK always outputs a free text report. _LUA_SCRIPT_NAME (above) # writes this prefix before the CSV output begins. _CSV_PREFIX = '==CSV==\n' def _Install(vm): vm.Install('build_tools') vm.Install('curl') vm.Install('openssl') vm.RemoteCommand( ( 'mkdir -p {0} && curl -L {1} | tar --strip-components=1 -C {0} -xzf -' ).format(WRK_DIR, WRK_URL) ) vm.RemoteCommand('cd {} && make'.format(WRK_DIR)) vm.PushDataFile(_LUA_SCRIPT_NAME, _LUA_SCRIPT_PATH) def YumInstall(vm): """Installs wrk on the VM.""" _Install(vm) def AptInstall(vm): """Installs wrk on the VM.""" _Install(vm) def _ParseOutput(output_text): """Parses the output of _LUA_SCRIPT_NAME. Yields: (variable_name, value, unit) tuples. """ if _CSV_PREFIX not in output_text: raise ValueError('{} not found in\n{}'.format(_CSV_PREFIX, output_text)) csv_fp = six.StringIO(str(output_text).rsplit(_CSV_PREFIX, 1)[-1]) reader = csv.DictReader(csv_fp) if frozenset(reader.fieldnames) != frozenset(['variable', 'value', 'unit']): raise ValueError('Unexpected fields: {}'.format(reader.fieldnames)) for row in reader: yield row['variable'], float(row['value']), row['unit'] def Run(vm, target, connections=1, duration=60): """Runs wrk against a given target. Args: vm: Virtual machine. target: URL to fetch. connections: Number of concurrent connections. duration: Duration of the test, in seconds. Yields: sample.Sample objects with results. """ threads = min(connections, vm.NumCpusForBenchmark()) cmd = ( '{wrk} --connections={connections} --threads={threads} ' '--duration={duration} ' '--timeout={timeout} ' '--script={script} {target}' ).format( wrk=WRK_PATH, connections=connections, threads=threads, script=_LUA_SCRIPT_PATH, target=target, duration=duration, timeout=_TIMEOUT, ) stdout, _ = vm.RemoteCommand(cmd) for variable, value, unit in _ParseOutput(stdout): yield sample.Sample( variable, value, unit, metadata={ 'connections': connections, 'threads': threads, 'duration': duration, }, )