Vivia Nikolaidou | 26bc65a | 2012-07-17 15:32:13 +0100 | [diff] [blame] | 1 | # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 5 | """Library to run fio scripts. |
| 6 | |
| 7 | fio_runner launch fio and collect results. |
| 8 | The output dictionary can be add to autotest keyval: |
| 9 | results = {} |
| 10 | results.update(fio_util.fio_runner(job_file, env_vars)) |
| 11 | self.write_perf_keyval(results) |
| 12 | |
| 13 | Decoding class can be invoked independently. |
| 14 | |
| 15 | """ |
| 16 | |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 17 | import json, logging, re, utils |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 18 | |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 19 | class fio_graph_generator(): |
| 20 | """ |
| 21 | Generate graph from fio log that created when specified these options. |
| 22 | - write_bw_log |
| 23 | - write_iops_log |
| 24 | - write_lat_log |
| 25 | |
| 26 | The following limitations apply |
| 27 | - Log file name must be in format jobname_testpass |
| 28 | - Graph is generate using Google graph api -> Internet require to view. |
| 29 | """ |
| 30 | |
| 31 | html_head = """ |
| 32 | <html> |
| 33 | <head> |
| 34 | <script type="text/javascript" src="https://www.google.com/jsapi"></script> |
| 35 | <script type="text/javascript"> |
| 36 | google.load("visualization", "1", {packages:["corechart"]}); |
| 37 | google.setOnLoadCallback(drawChart); |
| 38 | function drawChart() { |
| 39 | """ |
| 40 | |
| 41 | html_tail = """ |
| 42 | var chart_div = document.getElementById('chart_div'); |
| 43 | var chart = new google.visualization.ScatterChart(chart_div); |
| 44 | chart.draw(data, options); |
| 45 | } |
| 46 | </script> |
| 47 | </head> |
| 48 | <body> |
| 49 | <div id="chart_div" style="width: 100%; height: 100%;"></div> |
| 50 | </body> |
| 51 | </html> |
| 52 | """ |
| 53 | |
| 54 | h_title = { True: 'Percentile', False: 'Time (s)' } |
| 55 | v_title = { 'bw' : 'Bandwidth (KB/s)', |
| 56 | 'iops': 'IOPs', |
| 57 | 'lat' : 'Total latency (us)', |
| 58 | 'clat': 'Completion latency (us)', |
| 59 | 'slat': 'Submission latency (us)' } |
| 60 | graph_title = { 'bw' : 'bandwidth', |
| 61 | 'iops': 'IOPs', |
| 62 | 'lat' : 'total latency', |
| 63 | 'clat': 'completion latency', |
| 64 | 'slat': 'submission latency' } |
| 65 | |
| 66 | test_name = '' |
| 67 | test_type = '' |
| 68 | pass_list = '' |
| 69 | |
| 70 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 71 | def _parse_log_file(cls, file_name, pass_index, pass_count, percentile): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 72 | """ |
| 73 | Generate row for google.visualization.DataTable from one log file. |
| 74 | Log file is the one that generated using write_{bw,lat,iops}_log |
| 75 | option in the FIO job file. |
| 76 | |
| 77 | The fio log file format is timestamp, value, direction, blocksize |
| 78 | The output format for each row is { c: list of { v: value} } |
| 79 | |
| 80 | @param file_name: log file name to read data from |
| 81 | @param pass_index: index of current run pass |
| 82 | @param pass_count: number of all test run passes |
| 83 | @param percentile: flag to use percentile as key instead of timestamp |
| 84 | |
| 85 | @return: list of data rows in google.visualization.DataTable format |
| 86 | """ |
| 87 | # Read data from log |
| 88 | with open(file_name, 'r') as f: |
| 89 | data = [] |
| 90 | |
| 91 | for line in f.readlines(): |
| 92 | if not line: |
| 93 | break |
| 94 | t, v, _, _ = [int(x) for x in line.split(', ')] |
| 95 | data.append([t / 1000.0, v]) |
| 96 | |
| 97 | # Sort & calculate percentile |
| 98 | if percentile: |
| 99 | data.sort(key=lambda x:x[1]) |
| 100 | l = len(data) |
| 101 | for i in range(l): |
| 102 | data[i][0] = 100 * (i + 0.5) / l |
| 103 | |
| 104 | # Generate the data row |
| 105 | all_row = [] |
| 106 | row = [None] * (pass_count + 1) |
| 107 | for d in data: |
| 108 | row[0] = {'v' : '%.3f' % d[0]} |
| 109 | row[pass_index + 1] = {'v': d[1] } |
| 110 | all_row.append({'c': row[:]}) |
| 111 | |
| 112 | return all_row |
| 113 | |
| 114 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 115 | def _gen_data_col(cls, pass_list, percentile): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 116 | """ |
| 117 | Generate col for google.visualization.DataTable |
| 118 | |
| 119 | The output format is list of dict of label and type. In this case, |
| 120 | type is always number. |
| 121 | |
| 122 | @param pass_list: list of test run passes |
| 123 | @param percentile: flag to use percentile as key instead of timestamp |
| 124 | |
| 125 | @return: list of column in google.visualization.DataTable format |
| 126 | """ |
| 127 | if percentile: |
| 128 | col_name_list = ['percentile'] + pass_list |
| 129 | else: |
| 130 | col_name_list = ['time'] + pass_list |
| 131 | |
| 132 | return [{'label': name, 'type': 'number'} for name in col_name_list] |
| 133 | |
| 134 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 135 | def _gen_data_row(cls, test_name, test_type, pass_list, percentile): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 136 | """ |
| 137 | Generate row for google.visualization.DataTable by generate all log |
| 138 | file name and call _parse_log_file for each file |
| 139 | |
| 140 | @param test_name: name of current workload. i.e. randwrite |
| 141 | @param test_type: type of value collected for current test. i.e. IOPs |
| 142 | @param pass_list: list of run passes for current test |
| 143 | @param percentile: flag to use percentile as key instead of timestamp |
| 144 | |
| 145 | @return: list of data rows in google.visualization.DataTable format |
| 146 | """ |
| 147 | all_row = [] |
| 148 | pass_count = len(pass_list) |
| 149 | for pass_index, pass_str in enumerate(pass_list): |
| 150 | log_file_name = str('%s_%s_%s.log' % |
| 151 | (test_name, pass_str, test_type)) |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 152 | all_row.extend(cls._parse_log_file(log_file_name, pass_index, |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 153 | pass_count, percentile)) |
| 154 | return all_row |
| 155 | |
| 156 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 157 | def _write_data(cls, f, test_name, test_type, pass_list, percentile): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 158 | """ |
| 159 | Write google.visualization.DataTable object to output file. |
| 160 | https://developers.google.com/chart/interactive/docs/reference |
| 161 | |
| 162 | @param test_name: name of current workload. i.e. randwrite |
| 163 | @param test_type: type of value collected for current test. i.e. IOPs |
| 164 | @param pass_list: list of run passes for current test |
| 165 | @param percentile: flag to use percentile as key instead of timestamp |
| 166 | """ |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 167 | col = cls._gen_data_col(pass_list, percentile) |
| 168 | row = cls._gen_data_row(test_name, test_type, pass_list, percentile) |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 169 | data_dict = { 'cols' : col, 'rows' : row} |
| 170 | |
| 171 | f.write('var data = new google.visualization.DataTable(') |
| 172 | json.dump(data_dict, f) |
| 173 | f.write(');\n') |
| 174 | |
| 175 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 176 | def _write_option(cls, f, test_name, test_type, percentile): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 177 | """ |
| 178 | Write option to render scatter graph to output file. |
| 179 | https://google-developers.appspot.com/chart/interactive/docs/gallery/scatterchart |
| 180 | |
| 181 | @param test_name: name of current workload. i.e. randwrite |
| 182 | @param test_type: type of value collected for current test. i.e. IOPs |
| 183 | @param percentile: flag to use percentile as key instead of timestamp |
| 184 | """ |
| 185 | option = {'pointSize': 1 } |
| 186 | if percentile: |
| 187 | option['title'] = ('Percentile graph of %s for %s workload' % |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 188 | (cls.graph_title[test_type], test_name)) |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 189 | else: |
| 190 | option['title'] = ('Graph of %s for %s workload over time' % |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 191 | (cls.graph_title[test_type], test_name)) |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 192 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 193 | option['hAxis'] = { 'title': cls.h_title[percentile]} |
| 194 | option['vAxis'] = { 'title': cls.v_title[test_type]} |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 195 | |
| 196 | f.write('var options = ') |
| 197 | json.dump(option, f) |
| 198 | f.write(';\n') |
| 199 | |
| 200 | @classmethod |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 201 | def _write_graph(cls, test_name, test_type, pass_list, percentile=False): |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 202 | """ |
| 203 | Generate graph for test name / test type |
| 204 | |
| 205 | @param test_name: name of current workload. i.e. randwrite |
| 206 | @param test_type: type of value collected for current test. i.e. IOPs |
| 207 | @param pass_list: list of run passes for current test |
| 208 | @param percentile: flag to use percentile as key instead of timestamp |
| 209 | """ |
| 210 | logging.info('fio_graph_generator._write_graph %s %s %s', |
| 211 | test_name, test_type, str(pass_list)) |
| 212 | |
| 213 | |
| 214 | if percentile: |
| 215 | out_file_name = '%s_%s_percentile.html' % (test_name, test_type) |
| 216 | else: |
| 217 | out_file_name = '%s_%s.html' % (test_name, test_type) |
| 218 | |
| 219 | with open(out_file_name, 'w') as f: |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 220 | f.write(cls.html_head) |
| 221 | cls._write_data(f, test_name, test_type, pass_list, percentile) |
| 222 | cls._write_option(f, test_name, test_type, percentile) |
| 223 | f.write(cls.html_tail) |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 224 | |
| 225 | def __init__(self, test_name, test_type, pass_list): |
| 226 | """ |
| 227 | @param test_name: name of current workload. i.e. randwrite |
| 228 | @param test_type: type of value collected for current test. i.e. IOPs |
| 229 | @param pass_list: list of run passes for current test |
| 230 | """ |
| 231 | self.test_name = test_name |
| 232 | self.test_type = test_type |
| 233 | self.pass_list = pass_list |
| 234 | |
| 235 | def run(self): |
| 236 | """ |
| 237 | Run the graph generator. |
| 238 | """ |
| 239 | self._write_graph(self.test_name, self.test_type, self.pass_list, False) |
| 240 | self._write_graph(self.test_name, self.test_type, self.pass_list, True) |
| 241 | |
| 242 | |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 243 | def fio_parse_dict(d, prefix): |
| 244 | """ |
| 245 | Parse fio json dict |
| 246 | |
| 247 | Recursively flaten json dict to generate autotest perf dict |
| 248 | |
| 249 | @param d: input dict |
| 250 | @param prefix: name prefix of the key |
| 251 | """ |
| 252 | |
| 253 | # No need to parse something that didn't run such as read stat in write job. |
| 254 | if 'io_bytes' in d and d['io_bytes'] == 0: |
| 255 | return { } |
| 256 | |
| 257 | results = { } |
| 258 | for k, v in d.items(): |
| 259 | |
| 260 | # remove >, >=, <, <= |
| 261 | for c in '>=<': |
| 262 | k = k.replace(c, '') |
| 263 | |
| 264 | key = prefix + '_' + k |
| 265 | |
| 266 | if type(v) is dict: |
| 267 | results.update(fio_parse_dict(v, key)) |
| 268 | else: |
| 269 | results[key] = v |
| 270 | return results |
| 271 | |
| 272 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 273 | def fio_parser(lines, prefix=None): |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 274 | """ |
| 275 | Parse the json fio output |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 276 | |
| 277 | This collects all metrics given by fio and labels them according to unit |
| 278 | of measurement and test case name. |
| 279 | |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 280 | @param lines: text output of json fio output. |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 281 | @param prefix: prefix for result keys. |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 282 | """ |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 283 | results = { } |
| 284 | fio_dict = json.loads(lines) |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 285 | |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 286 | if prefix: |
| 287 | prefix = prefix + '_' |
| 288 | else: |
| 289 | prefix = '' |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 290 | |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 291 | results[prefix + 'fio_version'] = fio_dict['fio version'] |
| 292 | |
| 293 | if 'disk_util' in fio_dict: |
| 294 | results.update(fio_parse_dict(fio_dict['disk_util'][0], |
| 295 | prefix + 'disk')) |
| 296 | |
| 297 | for job in fio_dict['jobs']: |
| 298 | job_prefix = '_' + prefix + job['jobname'] |
| 299 | job.pop('jobname') |
| 300 | |
| 301 | |
| 302 | for k, v in job.iteritems(): |
| 303 | results.update(fio_parse_dict({k:v}, job_prefix)) |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 304 | |
| 305 | return results |
| 306 | |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 307 | def fio_generate_graph(): |
| 308 | """ |
| 309 | Scan for fio log file in output directory and send data to generate each |
| 310 | graph to fio_graph_generator class. |
| 311 | """ |
| 312 | log_types = ['bw', 'iops', 'lat', 'clat', 'slat'] |
| 313 | |
| 314 | # move fio log to result dir |
| 315 | for log_type in log_types: |
| 316 | logging.info('log_type %s', log_type) |
| 317 | logs = utils.system_output('ls *_%s.log' % log_type, ignore_status=True) |
| 318 | if not logs: |
| 319 | continue |
| 320 | |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 321 | pattern = r"""(?P<jobname>.*)_ # jobname |
| 322 | ((?P<runpass>p\d+)_) # pass |
| 323 | (?P<type>bw|iops|lat|clat|slat).log # type |
| 324 | """ |
| 325 | matcher = re.compile(pattern, re.X) |
| 326 | |
| 327 | pass_list = [] |
| 328 | current_job = '' |
| 329 | |
| 330 | for log in logs.split(): |
| 331 | match = matcher.match(log) |
| 332 | if not match: |
| 333 | logging.warn('Unknown log file %s', log) |
| 334 | continue |
| 335 | |
| 336 | jobname = match.group('jobname') |
| 337 | runpass = match.group('runpass') |
| 338 | |
| 339 | # All files for particular job name are group together for create |
| 340 | # graph that can compare performance between result from each pass. |
| 341 | if jobname != current_job: |
| 342 | if pass_list: |
| 343 | fio_graph_generator(current_job, log_type, pass_list).run() |
| 344 | current_job = jobname |
| 345 | pass_list = [] |
| 346 | |
| 347 | pass_list.append(runpass) |
| 348 | |
| 349 | if pass_list: |
| 350 | fio_graph_generator(current_job, log_type, pass_list).run() |
| 351 | |
| 352 | |
| 353 | cmd = 'mv *_%s.log results' % log_type |
| 354 | utils.run(cmd, ignore_status=True) |
| 355 | utils.run('mv *.html results', ignore_status=True) |
| 356 | |
| 357 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 358 | def fio_runner(test, job, env_vars, |
| 359 | name_prefix=None, |
| 360 | graph_prefix=None): |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 361 | """ |
| 362 | Runs fio. |
| 363 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 364 | Build a result keyval and performence json. |
| 365 | The JSON would look like: |
| 366 | {"description": "<name_prefix>_<modle>_<size>G", |
| 367 | "graph": "<graph_prefix>_1m_write_wr_lat_99.00_percent_usec", |
| 368 | "higher_is_better": false, "units": "us", "value": "xxxx"} |
| 369 | {... |
| 370 | |
| 371 | |
Puthikorn Voravootivat | 425b1a7 | 2014-05-14 17:33:27 -0700 | [diff] [blame] | 372 | @param test: test to upload perf value |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 373 | @param job: fio config file to use |
| 374 | @param env_vars: environment variable fio will substituete in the fio |
| 375 | config file. |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 376 | @param name_prefix: prefix of the descriptions to use in chrome perfi |
| 377 | dashboard. |
| 378 | @param graph_prefix: prefix of the graph name in chrome perf dashboard |
| 379 | and result keyvals. |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 380 | @return fio results. |
| 381 | |
| 382 | """ |
| 383 | |
| 384 | # running fio with ionice -c 3 so it doesn't lock out other |
| 385 | # processes from the disk while it is running. |
| 386 | # If you want to run the fio test for performance purposes, |
| 387 | # take out the ionice and disable hung process detection: |
| 388 | # "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" |
| 389 | # -c 3 = Idle |
| 390 | # Tried lowest priority for "best effort" but still failed |
| 391 | ionice = 'ionice -c 3' |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 392 | options = ['--output-format=json'] |
Gwendal Grignou | 29d2af5 | 2014-05-02 11:32:27 -0700 | [diff] [blame] | 393 | fio_cmd_line = ' '.join([env_vars, ionice, 'fio', |
| 394 | ' '.join(options), |
| 395 | '"' + job + '"']) |
| 396 | fio = utils.run(fio_cmd_line) |
| 397 | |
| 398 | logging.debug(fio.stdout) |
Puthikorn Voravootivat | 1696136 | 2014-05-07 15:57:27 -0700 | [diff] [blame] | 399 | |
| 400 | fio_generate_graph() |
| 401 | |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 402 | filename = re.match('.*FILENAME=(?P<f>[^ ]*)', env_vars).group('f') |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 403 | diskname = utils.get_disk_from_filename(filename) |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 404 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 405 | if diskname: |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 406 | model = utils.get_disk_model(diskname) |
| 407 | size = utils.get_disk_size_gb(diskname) |
| 408 | perfdb_name = '%s_%dG' % (model, size) |
| 409 | else: |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 410 | perfdb_name = filename.replace('/', '_') |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 411 | |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 412 | if name_prefix: |
| 413 | perfdb_name = name_prefix + '_' + perfdb_name |
| 414 | |
Gwendal Grignou | 51d5069 | 2014-06-20 11:42:18 -0700 | [diff] [blame] | 415 | result = fio_parser(fio.stdout, prefix=name_prefix) |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 416 | if not graph_prefix: |
| 417 | graph_prefix = '' |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 418 | |
Puthikorn Voravootivat | 425b1a7 | 2014-05-14 17:33:27 -0700 | [diff] [blame] | 419 | for k, v in result.iteritems(): |
Gwendal Grignou | 2f16f2f | 2014-06-12 11:28:05 -0700 | [diff] [blame] | 420 | # Remove the prefix for value, and replace it the graph prefix. |
Gwendal Grignou | 51d5069 | 2014-06-20 11:42:18 -0700 | [diff] [blame] | 421 | if name_prefix: |
| 422 | k = k.replace('_' + name_prefix, graph_prefix) |
Puthikorn Voravootivat | 16dc0a2 | 2014-06-24 10:52:04 -0700 | [diff] [blame] | 423 | |
| 424 | # Make graph name to be same as the old code. |
| 425 | if k.endswith('bw'): |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 426 | test.output_perf_value(description=perfdb_name, graph=k, value=v, |
| 427 | units='KB_per_sec', higher_is_better=True) |
Puthikorn Voravootivat | f5ebc66 | 2014-07-11 16:34:49 -0700 | [diff] [blame] | 428 | elif k.rstrip('0').endswith('clat_percentile_99.'): |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 429 | test.output_perf_value(description=perfdb_name, graph=k, value=v, |
| 430 | units='us', higher_is_better=False) |
Puthikorn Voravootivat | 425b1a7 | 2014-05-14 17:33:27 -0700 | [diff] [blame] | 431 | return result |