kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 1 | import logging |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 2 | from typing import cast, Iterator, List, Union |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 3 | |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 4 | import numpy |
| 5 | |
| 6 | from cephlib.common import float2str |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 7 | from cephlib.texttable import Texttable |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 8 | from cephlib.statistic import calc_norm_stat_props, calc_histo_stat_props |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 9 | |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 10 | from .stage import Stage, StepOrder |
| 11 | from .test_run_class import TestRun |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 12 | from .result_classes import SuiteConfig |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 13 | from .suits.io.fio import FioTest |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 14 | from .suits.io.fio_job import FioJobParams |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 15 | from .suits.io.fio_hist import get_lat_vals |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 16 | from .data_selectors import get_aggregated |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 17 | from .result_storage import IWallyStorage |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 18 | |
| 19 | |
| 20 | logger = logging.getLogger("wally") |
| 21 | |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 22 | |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 23 | |
| 24 | console_report_headers = ["Description", "IOPS ~ Dev", "BW, MiBps", 'Skew/Kurt', 'lat med, ms', 'lat 95, ms'] |
| 25 | console_report_align = ['l', 'r', 'r', 'r', 'r', 'r'] |
| 26 | |
| 27 | def get_console_report_table(suite: SuiteConfig, rstorage: IWallyStorage) -> List[Union[List[str], Texttable.HLINE]]: |
| 28 | table = [] # type: List[Union[List[str], Texttable.HLINE]] |
| 29 | prev_params = None |
| 30 | for job in sorted(rstorage.iter_job(suite), key=lambda job: job.params): |
| 31 | fparams = cast(FioJobParams, job.params) |
| 32 | fparams['qd'] = None |
| 33 | |
| 34 | if prev_params is not None and fparams.char_tpl != prev_params: |
| 35 | table.append(Texttable.HLINE) |
| 36 | |
| 37 | prev_params = fparams.char_tpl |
| 38 | |
| 39 | bw_ts = get_aggregated(rstorage, suite.storage_id, job.storage_id, metric='bw', |
| 40 | trange=job.reliable_info_range_s) |
| 41 | props = calc_norm_stat_props(bw_ts) |
| 42 | avg_iops = props.average // job.params.params['bsize'] |
| 43 | iops_dev = props.deviation // job.params.params['bsize'] |
| 44 | |
| 45 | lat_ts = get_aggregated(rstorage, suite.storage_id, job.storage_id, metric='lat', |
| 46 | trange=job.reliable_info_range_s) |
| 47 | bins_edges = numpy.array(get_lat_vals(lat_ts.data.shape[1]), dtype='float32') / 1000 # convert us to ms |
| 48 | lat_props = calc_histo_stat_props(lat_ts, bins_edges) |
| 49 | table.append([job.params.summary, |
| 50 | "{:>6s} ~ {:>6s}".format(float2str(avg_iops), float2str(iops_dev)), |
| 51 | float2str(props.average / 1024), # Ki -> Mi |
| 52 | "{:>5.1f}/{:>5.1f}".format(props.skew, props.kurt), |
| 53 | float2str(lat_props.perc_50), float2str(lat_props.perc_95)]) |
| 54 | return table |
| 55 | |
| 56 | |
kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 57 | class ConsoleReportStage(Stage): |
| 58 | |
| 59 | priority = StepOrder.REPORT |
| 60 | |
| 61 | def run(self, ctx: TestRun) -> None: |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 62 | for suite in ctx.rstorage.iter_suite(FioTest.name): |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 63 | table = Texttable(max_width=200) |
| 64 | table.set_deco(Texttable.VLINES | Texttable.BORDER | Texttable.HEADER) |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 65 | tbl = ctx.rstorage.get_txt_report(suite) |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 66 | if tbl is None: |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame^] | 67 | table.header(console_report_headers) |
| 68 | table.set_cols_align(console_report_align) |
| 69 | for line in get_console_report_table(suite, ctx.rstorage): |
| 70 | table.add_row(line) |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 71 | tbl = table.draw() |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 72 | ctx.rstorage.put_txt_report(suite, tbl) |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 73 | print(tbl) |