diff options
-rw-r--r-- | samples/fio.yaml | 43 | ||||
-rw-r--r-- | tests/unit/benchmark/scenarios/storage/fio_sample_output.json | 1 | ||||
-rw-r--r-- | tests/unit/benchmark/scenarios/storage/test_fio.py | 23 | ||||
-rw-r--r-- | yardstick/benchmark/scenarios/storage/fio.py | 39 | ||||
-rw-r--r-- | yardstick/benchmark/scenarios/storage/fio_benchmark.bash | 43 | ||||
-rw-r--r-- | yardstick/dispatcher/file.py | 3 | ||||
-rw-r--r-- | yardstick/plot/plotter.py | 16 |
7 files changed, 60 insertions, 108 deletions
diff --git a/samples/fio.yaml b/samples/fio.yaml index 44444c7cc..083c57549 100644 --- a/samples/fio.yaml +++ b/samples/fio.yaml @@ -2,48 +2,13 @@ # Sample benchmark task config file # measure storage performance using fio # -# For this sample just like running the command below on the test vm and +# For this sample just like running the command below on the test vm and # getting benchmark info back to the yardstick. # -# sudo fio -filename=/home/ec2-user/data.raw -bs=4k -ipdepth=1 -rw=write \ +# sudo fio -filename=/home/ec2-user/data.raw -bs=4k -ipdepth=1 -rw=rw \ # -ramp_time=10 -runtime=60 -name=yardstick-fio -ioengine=libaio \ # -direct=1 -group_reporting -numjobs=1 -time_based \ -# --output=yardstick-fio.log -# -# When the above fio command done, the yardstick-fio.log file will contain -# information like below and the benchmark script will take iops, throughput -# and latency info marked with "" to create json style output. -# -# yardstick-fio: (g=0): rw=write, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=1 -# fio-2.1.3 -# Starting 1 process -# -# yardstick-fio: (groupid=0, jobs=1): err= 0: pid=1421: Mon Jul 6 01:25:41 2015 -# write: io=1985.4MB, bw=33882KB/s, iops="8470", runt= 60001msec -# slat (usec): min=6, max=15049, avg=10.29, stdev=19.42 -# clat (usec): min=1, max=18517, avg=105.68, stdev=37.76 -# lat ("usec"): min=85, max=18528, avg="116.30", stdev=43.57 -# clat percentiles (usec): -# | 1.00th=[ 83], 5.00th=[ 85], 10.00th=[ 87], 20.00th=[ 88], -# | 30.00th=[ 90], 40.00th=[ 93], 50.00th=[ 98], 60.00th=[ 102], -# | 70.00th=[ 110], 80.00th=[ 124], 90.00th=[ 137], 95.00th=[ 149], -# | 99.00th=[ 173], 99.50th=[ 181], 99.90th=[ 203], 99.95th=[ 290], -# | 99.99th=[ 604] -# bw (KB /s): min= 0, max=39816, per=99.26%, avg=33631.46, stdev=4369.58 -# lat (usec) : 2=0.01%, 50=0.01%, 100=55.44%, 250=44.50%, 500=0.02% -# lat (usec) : 750=0.04%, 1000=0.01% -# lat (msec) : 2=0.01%, 4=0.01%, 10=0.01%, 20=0.01% -# cpu : usr=4.09%, sys=16.38%, ctx=604931, majf=0, minf=27 -# IO depths : 1=118.9%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0% -# submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% -# complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% -# issued : total=r=0/w=508237/d=0, short=r=0/w=0/d=0 -# -# Run status group 0 (all jobs): -# WRITE: io=1985.4MB, aggrb="33881KB/s", minb=33881KB/s, maxb=33881KB/s, mint=60001msec, maxt=60001msec -# -# Disk stats (read/write): -# vda: ios=0/604235, merge=0/211, ticks=0/61964, in_queue=61804, util=86.25% +# --output-format=json schema: "yardstick:task:0.1" @@ -54,7 +19,7 @@ scenarios: filename: /home/ec2-user/data.raw bs: 4k iodepth: 1 - rw: write + rw: rw ramp_time: 10 host: fio.demo runner: diff --git a/tests/unit/benchmark/scenarios/storage/fio_sample_output.json b/tests/unit/benchmark/scenarios/storage/fio_sample_output.json new file mode 100644 index 000000000..4c7501818 --- /dev/null +++ b/tests/unit/benchmark/scenarios/storage/fio_sample_output.json @@ -0,0 +1 @@ +{"jobs": [{"trim": {"io_bytes": 0, "slat": {"max": 0, "mean": 0.0, "stddev": 0.0, "min": 0}, "bw_max": 0, "bw_mean": 0.0, "iops": 0, "bw": 0, "lat": {"max": 0, "mean": 0.0, "stddev": 0.0, "min": 0}, "bw_agg": 0.0, "clat": {"max": 0, "mean": 0.0, "percentile": {"70.000000": 0, "5.000000": 0, "50.000000": 0, "99.990000": 0, "30.000000": 0, "10.000000": 0, "99.000000": 0, "0.00": 0, "90.000000": 0, "95.000000": 0, "60.000000": 0, "40.000000": 0, "20.000000": 0, "99.900000": 0, "99.950000": 0, "1.000000": 0, "99.500000": 0, "80.000000": 0}, "stddev": 0.0, "min": 0}, "runtime": 0, "bw_min": 0, "bw_dev": 0.0}, "latency_us": {"10": 0.01, "750": 0.03, "20": 0.0, "50": 0.02, "2": 0.01, "4": 0.01, "100": 0.75, "250": 88.37, "500": 10.72, "1000": 0.01}, "latency_ms": {"10": 0.01, "750": 0.0, "20": 0.01, ">=2000": 0.0, "50": 0.01, "2000": 0.0, "2": 0.07, "4": 0.01, "100": 0.0, "250": 0.01, "500": 0.0, "1000": 0.01}, "read": {"io_bytes": 839056, "slat": {"max": 1990, "mean": 18.14, "stddev": 15.4, "min": 0}, "bw_max": 10328, "bw_mean": 8721.27, "iops": 20972, "bw": 83888, "lat": {"max": 776676, "mean": 236.8, "stddev": 4668.12, "min": 45}, "bw_agg": 8721.27, "clat": {"max": 776663, "mean": 217.79, "percentile": {"70.000000": 199, "5.000000": 119, "50.000000": 175, "99.990000": 15168, "30.000000": 155, "10.000000": 131, "99.000000": 342, "0.00": 0, "90.000000": 247, "95.000000": 278, "60.000000": 185, "40.000000": 165, "20.000000": 145, "99.900000": 820, "99.950000": 1272, "1.000000": 96, "99.500000": 370, "80.000000": 217}, "stddev": 4667.79, "min": 0}, "runtime": 10002, "bw_min": 4, "bw_dev": 2178.08}, "majf": 0, "ctx": 490590, "minf": 87, "jobname": "yardstick-fio", "write": {"io_bytes": 841992, "slat": {"max": 2594, "mean": 19.78, "stddev": 16.25, "min": 0}, "bw_max": 10472, "bw_mean": 8464.0, "iops": 21045, "bw": 84182, "lat": {"max": 776709, "mean": 233.55, "stddev": 3115.46, "min": 64}, "bw_agg": 8464.0, "clat": {"max": 776685, "mean": 212.87, "percentile": {"70.000000": 211, "5.000000": 135, "50.000000": 187, "99.990000": 3536, "30.000000": 169, "10.000000": 145, "99.000000": 358, "0.00": 0, "90.000000": 258, "95.000000": 290, "60.000000": 197, "40.000000": 177, "20.000000": 159, "99.900000": 756, "99.950000": 1288, "1.000000": 114, "99.500000": 382, "80.000000": 229}, "stddev": 3115.23, "min": 0}, "runtime": 10002, "bw_min": 4, "bw_dev": 2584.23}, "iodepth_level": {"16": 0.0, "32": 0.0, "1": 111.92, "2": 0.0, "4": 0.0, ">=64": 0.0, "8": 0.0}, "usr_cp": 2.87, "error": 0, "sys_cp": 12.37, "groupid": 0}], "fio version": "fio-2.1.3", "disk_util": [{"aggr_write_ticks": 42020, "read_merges": 0, "name": "dm-0", "write_ios": 233547, "aggr_write_ios": 235129, "aggr_read_ticks": 42576, "read_ios": 233492, "util": 97.22, "read_ticks": 42096, "aggr_write_merge": 0, "write_merges": 0, "aggr_in_queue": 84524, "aggr_read_ios": 235224, "aggr_util": 96.96, "aggr_read_merges": 0, "in_queue": 83732, "write_ticks": 41468}, {"read_merges": 0, "name": "vda", "write_ios": 235129, "read_ios": 235224, "util": 96.96, "read_ticks": 42576, "write_merges": 0, "in_queue": 84524, "write_ticks": 42020}]} diff --git a/tests/unit/benchmark/scenarios/storage/test_fio.py b/tests/unit/benchmark/scenarios/storage/test_fio.py index 54f493ee6..45e8a9429 100644 --- a/tests/unit/benchmark/scenarios/storage/test_fio.py +++ b/tests/unit/benchmark/scenarios/storage/test_fio.py @@ -14,6 +14,7 @@ import mock import unittest import json +import os from yardstick.benchmark.scenarios.storage import fio @@ -34,7 +35,7 @@ class FioTestCase(unittest.TestCase): options = { 'filename': "/home/ec2-user/data.raw", 'bs': "4k", - 'rw': "write", + 'rw': "rw", 'ramp_time': 10 } args = {'options': options} @@ -50,19 +51,21 @@ class FioTestCase(unittest.TestCase): options = { 'filename': "/home/ec2-user/data.raw", 'bs': "4k", - 'rw': "write", + 'rw': "rw", 'ramp_time': 10 } args = {'options': options} p.client = mock_ssh.SSH() - sample_output = '{"read_bw": "N/A", "write_lat": "407.08usec", \ - "read_iops": "N/A", "write_bw": "9507KB/s", \ - "write_iops": "2376", "read_lat": "N/A"}' + sample_output = self._read_sample_output() mock_ssh.SSH().execute.return_value = (0, sample_output, '') result = p.run(args) - expected_result = json.loads(sample_output) + + expected_result = '{"read_bw": 83888, "read_iops": 20972,' \ + '"read_lat": 236.8, "write_bw": 84182, "write_iops": 21045,'\ + '"write_lat": 233.55}' + expected_result = json.loads(expected_result) self.assertEqual(result, expected_result) def test_fio_unsuccessful_script_error(self, mock_ssh): @@ -71,7 +74,7 @@ class FioTestCase(unittest.TestCase): options = { 'filename': "/home/ec2-user/data.raw", 'bs': "4k", - 'rw': "write", + 'rw': "rw", 'ramp_time': 10 } args = {'options': options} @@ -80,6 +83,12 @@ class FioTestCase(unittest.TestCase): mock_ssh.SSH().execute.return_value = (1, '', 'FOOBAR') self.assertRaises(RuntimeError, p.run, args) + def _read_sample_output(self): + curr_path = os.path.dirname(os.path.abspath(__file__)) + output = os.path.join(curr_path, 'fio_sample_output.json') + with open(output) as f: + sample_output = f.read() + return sample_output def main(): unittest.main() diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py index d3695165f..42f159164 100644 --- a/yardstick/benchmark/scenarios/storage/fio.py +++ b/yardstick/benchmark/scenarios/storage/fio.py @@ -17,7 +17,7 @@ LOG = logging.getLogger(__name__) class Fio(base.Scenario): - """Execute fio benchmark on host + """Execute fio benchmark in a host Parameters filename - file name for fio workload @@ -73,8 +73,9 @@ class Fio(base.Scenario): def run(self, args): """execute the benchmark""" - default_args = "-ioengine=libaio -direct=1 " \ - "-group_reporting -numjobs=1 -time_based" + default_args = "-ioengine=libaio -direct=1 -group_reporting " \ + "-numjobs=1 -time_based --output-format=json" + result = {} if not self.setup_done: self.setup() @@ -97,21 +98,32 @@ class Fio(base.Scenario): else: runtime = 30 - args = "-filename=%s -bs=%s -iodepth=%s -rw=%s -ramp_time=%s " \ - "-runtime=%s -name=%s" \ - % (filename, bs, iodepth, rw, ramp_time, runtime, name) - cmd = "sudo bash fio.sh %s %s %s" \ - % (filename, args, default_args) + cmd_args = "-filename=%s -bs=%s -iodepth=%s -rw=%s -ramp_time=%s " \ + "-runtime=%s -name=%s %s" \ + % (filename, bs, iodepth, rw, ramp_time, runtime, name, + default_args) + cmd = "sudo bash fio.sh %s %s" % (filename, cmd_args) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) + # Set timeout, so that the cmd execution does not exit incorrectly + # when the test run time is last long + timeout = int(ramp_time) + int(runtime) + 600 + status, stdout, stderr = self.client.execute(cmd, timeout=timeout) if status: raise RuntimeError(stderr) - data = json.loads(stdout) + raw_data = json.loads(stdout) + + # The bandwidth unit is KB/s, and latency unit is us + result["read_bw"] = raw_data["jobs"][0]["read"]["bw"] + result["read_iops"] = raw_data["jobs"][0]["read"]["iops"] + result["read_lat"] = raw_data["jobs"][0]["read"]["lat"]["mean"] + result["write_bw"] = raw_data["jobs"][0]["write"]["bw"] + result["write_iops"] = raw_data["jobs"][0]["write"]["iops"] + result["write_lat"] = raw_data["jobs"][0]["write"]["lat"]["mean"] # TODO: add sla check - return data + return result def _test(): @@ -133,8 +145,9 @@ def _test(): "filename": "/home/ec2-user/data.raw", "bs": "4k", "iodepth": "1", - "rw": "write", - "ramp_time": 10, + "rw": "rw", + "ramp_time": 1, + "duration": 10 } args = {"options": options} diff --git a/yardstick/benchmark/scenarios/storage/fio_benchmark.bash b/yardstick/benchmark/scenarios/storage/fio_benchmark.bash index 0fa319dd4..2ef7f4949 100644 --- a/yardstick/benchmark/scenarios/storage/fio_benchmark.bash +++ b/yardstick/benchmark/scenarios/storage/fio_benchmark.bash @@ -15,7 +15,6 @@ set -e FIO_FILENAME=$1 shift OPTIONS="$@" -OUTPUT_FILE="yardstick-fio.log" # setup data file for fio setup() @@ -25,43 +24,10 @@ setup() fi } -# run fio test +# run fio test and write json format result to stdout run_test() { - fio $OPTIONS --output=$OUTPUT_FILE -} - -# write the result to stdout in json format -output_json() -{ - read_bw=$(grep "READ.*aggrb" $OUTPUT_FILE | awk -F [=\ ,] '{printf $9}') - write_bw=$(grep "WRITE.*aggrb" $OUTPUT_FILE | awk -F [=\ ,] '{printf $8}') - eval $(grep -e '\ lat.*stdev' -e "read.*iops" -e "write.*iops" -e "trim.*iops" $OUTPUT_FILE | sed 'N;s/\n/ /g' | grep read | awk -F [=\ ,\(\)] '{printf("read_iops=%s; read_lat_unit=%s; read_lat=%s", $12, $24, $33)}') - eval $(grep -e '\ lat.*stdev' -e "read.*iops" -e "write.*iops" -e "trim.*iops" $OUTPUT_FILE | sed 'N;s/\n/ /g' | grep write | awk -F [=\ ,\(\)] '{printf("write_iops=%s; write_lat_unit=%s; write_lat=%s", $11, $23, $32)}') - - read_bw=${read_bw:-N/A} - write_bw=${write_bw:-N/A} - read_iops=${read_iops:-N/A} - write_iops=${write_iops:-N/A} - if [ "x$read_lat" = "x" ]; then - read_lat="N/A" - else - read_lat=$read_lat$read_lat_unit - fi - if [ "x$write_lat" = "x" ]; then - write_lat="N/A" - else - write_lat=$write_lat$write_lat_unit - fi - - echo -e "{ \ - \"read_bw\":\"$read_bw\", \ - \"write_bw\":\"$write_bw\", \ - \"read_iops\":\"$read_iops\", \ - \"write_iops\":\"$write_iops\", \ - \"read_lat\":\"$read_lat\", \ - \"write_lat\":\"$write_lat\" \ - }" + fio $OPTIONS } # main entry @@ -71,10 +37,7 @@ main() setup # run the test - run_test >/dev/null - - # output result - output_json + run_test } main diff --git a/yardstick/dispatcher/file.py b/yardstick/dispatcher/file.py index 7c644f82f..dc39f152e 100644 --- a/yardstick/dispatcher/file.py +++ b/yardstick/dispatcher/file.py @@ -8,6 +8,7 @@ ############################################################################## import logging +import json from yardstick.dispatcher.base import Base as DispatchBase @@ -50,4 +51,4 @@ class FileDispatcher(DispatchBase): def record_result_data(self, data): if self.log: - self.log.info(data) + self.log.info(json.dumps(data)) diff --git a/yardstick/plot/plotter.py b/yardstick/plot/plotter.py index f3fb75d3e..0455386b5 100644 --- a/yardstick/plot/plotter.py +++ b/yardstick/plot/plotter.py @@ -213,16 +213,16 @@ class Plotter(object): is_rw_type = rw_types[i] == "rw" or rw_types[i] == "randrw" if is_r_type or is_rw_type: - # Remove trailing 'usec' and convert to float + # Convert to float data['read_lat'] = \ - [r['benchmark']['data']['read_lat'][:-4] for r in records] + [r['benchmark']['data']['read_lat'] for r in records] data['read_lat'] = \ [float(i) for i in data['read_lat']] - # Remove trailing 'KB/s' and convert to float + # Convert to int data['read_bw'] = \ - [r['benchmark']['data']['read_bw'][:-4] for r in records] + [r['benchmark']['data']['read_bw'] for r in records] data['read_bw'] = \ - [float(i) for i in data['read_bw']] + [int(i) for i in data['read_bw']] # Convert to int data['read_iops'] = \ [r['benchmark']['data']['read_iops'] for r in records] @@ -231,14 +231,14 @@ class Plotter(object): if is_w_type or is_rw_type: data['write_lat'] = \ - [r['benchmark']['data']['write_lat'][:-4] for r in records] + [r['benchmark']['data']['write_lat'] for r in records] data['write_lat'] = \ [float(i) for i in data['write_lat']] data['write_bw'] = \ - [r['benchmark']['data']['write_bw'][:-4] for r in records] + [r['benchmark']['data']['write_bw'] for r in records] data['write_bw'] = \ - [float(i) for i in data['write_bw']] + [int(i) for i in data['write_bw']] data['write_iops'] = \ [r['benchmark']['data']['write_iops'] for r in records] |