Home | History | Annotate | Download | only in hwbinder_latency_test
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (C) 2017 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 import json
     19 import logging
     20 
     21 from vts.runners.host import asserts
     22 from vts.runners.host import base_test
     23 from vts.runners.host import const
     24 from vts.runners.host import test_runner
     25 from vts.utils.python.controllers import android_device
     26 from vts.utils.python.cpu import cpu_frequency_scaling
     27 
     28 
     29 class HwBinderLatencyTest(base_test.BaseTestClass):
     30     """A test case for the hwbinder latency benchmarking.
     31 
     32     Sample output of libhwbinder_latency
     33     {
     34       "cfg":{"pair":6,"iterations":166,"deadline_us":2500,"passthrough":1},
     35       "fifo_0_data": [15052, ...],
     36       "fifo_1_data": [...],
     37       ...
     38       "ALL":{"SYNC":"GOOD","S":1992,"I":1992,"R":1,
     39         "other_ms":{ "avg":0.0048, "wst":0.32, "bst":0.0022, "miss":0, "meetR":1},
     40         "fifo_ms": { "avg":0.0035, "wst":0.037, "bst":0.0021, "miss":0, "meetR":1},
     41         "otherdis":{ "p50":0.19531, "p90":0.19531, "p95":0.19531, "p99": 0.19531},
     42         "fifodis": { "p50":0.19531, "p90":0.19531, "p95":0.19531, "p99": 0.19531}
     43       },
     44       "P0":{...
     45       },
     46       ...
     47       "inheritance": "PASS"
     48     }
     49     """
     50     # The order of the columns in the output table
     51     _MS_COLUMNS = ["avg", "wst", "bst", "miss", "meetR"]
     52     _DIS_COLUMNS = ["p50", "p90", "p95", "p99"]
     53     # The keys in the JSON object
     54     _CFG = "cfg"
     55     _PAIR = "pair"
     56     _ALL = "ALL"
     57     _OTHER_MS = "other_ms"
     58     _FIFO_MS = "fifo_ms"
     59     _OTHERDIS = "otherdis"
     60     _FIFODIS = "fifodis"
     61     _INHERITANCE = "inheritance"
     62 
     63     def setUpClass(self):
     64         required_params = ["hidl_hal_mode"]
     65         self.getUserParams(required_params)
     66         self.dut = self.registerController(android_device)[0]
     67         self.dut.shell.InvokeTerminal("one")
     68         self._cpu_freq = cpu_frequency_scaling.CpuFrequencyScalingController(self.dut)
     69         self._cpu_freq.DisableCpuScaling()
     70 
     71     def setUp(self):
     72         self._cpu_freq.SkipIfThermalThrottling(retry_delay_secs=30)
     73 
     74     def tearDown(self):
     75         self._cpu_freq.SkipIfThermalThrottling()
     76 
     77     def tearDownClass(self):
     78         self._cpu_freq.EnableCpuScaling()
     79 
     80     def testRunBenchmark32Bit(self):
     81         result = self._runBenchmark(32)
     82         self._addBenchmarkTableToResult(result, 32)
     83         self._uploadResult(result, 32)
     84 
     85     def testRunBenchmark64Bit(self):
     86         result = self._runBenchmark(64)
     87         self._addBenchmarkTableToResult(result, 64)
     88         self._uploadResult(result, 64)
     89 
     90     def _runBenchmark(self, bits):
     91         """Runs the native binary and parses its result.
     92 
     93         Args:
     94             bits: integer (32 or 64), the bitness of the binary to run.
     95 
     96         Returns:
     97             dict, the benchmarking result converted from native binary's JSON
     98             output.
     99         """
    100         logging.info("Start %d-bit hwbinder latency test with HIDL mode=%s",
    101                      bits, self.hidl_hal_mode)
    102         binary = "/data/local/tmp/%s/libhwbinder_latency%s" % (bits, bits)
    103         min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo()
    104         iterations = 1000 // (max_cpu - min_cpu)
    105         results = self.dut.shell.one.Execute([
    106             "chmod 755 %s" % binary,
    107             "VTS_ROOT_PATH=/data/local/tmp " \
    108             "LD_LIBRARY_PATH=/system/lib%s:/data/local/tmp/%s/hw:"
    109             "/data/local/tmp/%s:$LD_LIBRARY_PATH "
    110             "%s -raw_data -pair %d -i %d -m %s" % (bits, bits, bits,
    111                 binary, max_cpu - min_cpu, iterations,
    112                 self.hidl_hal_mode.encode("utf-8"))])
    113         # Parses the result.
    114         asserts.assertEqual(len(results[const.STDOUT]), 2)
    115         logging.info("stderr: %s", results[const.STDERR][1])
    116         logging.info("stdout: %s", results[const.STDOUT][1])
    117         asserts.assertFalse(
    118             any(results[const.EXIT_CODE]),
    119             "testRunBenchmark%sBit failed." % (bits))
    120         json_result = json.loads(results[const.STDOUT][1]);
    121         asserts.assertTrue(json_result[self._INHERITANCE] == "PASS",
    122             "Scheduler does not support priority inheritance.");
    123         return json_result
    124 
    125     def _createRow(self, pair_name, ms_result, dis_result):
    126         """Creates a row from the JSON output.
    127 
    128         Args:
    129             pair_name: string, the pair name in the first column.
    130             ms_result: dict, the fifo_ms or other_ms object.
    131             dis_result: dict, the fifodis or otherdis object.
    132 
    133         Returns:
    134             the list containing pair_name and the values in the objects.
    135         """
    136         row = [pair_name]
    137         row.extend([ms_result[x] for x in self._MS_COLUMNS])
    138         row.extend([dis_result[x] for x in self._DIS_COLUMNS])
    139         return row
    140 
    141     def _addBenchmarkTableToResult(self, result, bits):
    142         pair_cnt = result[self._CFG][self._PAIR]
    143         row_names = ["P" + str(i) for i in range(pair_cnt)] + [self._ALL]
    144         col_names = ["pair"] + self._MS_COLUMNS + self._DIS_COLUMNS
    145         fifo_table = [col_names]
    146         other_table = [col_names]
    147         for row_name in row_names:
    148             pair_result = result[row_name]
    149             fifo_table.append(self._createRow(row_name,
    150                 pair_result[self._FIFO_MS], pair_result[self._FIFODIS]))
    151             other_table.append(self._createRow(row_name,
    152                 pair_result[self._OTHER_MS], pair_result[self._OTHERDIS]))
    153         self.addTableToResult(
    154             "hwbinder_latency_%sbits_fifo" % bits,fifo_table)
    155         self.addTableToResult(
    156             "hwbinder_latency_%sbits_other" % bits, other_table)
    157 
    158     def _uploadResult(self, result, bits):
    159         """Uploads the output of benchmark program to web DB.
    160 
    161         Args:
    162             result: dict which is the benchmarking result.
    163             bits: integer (32 or 64).
    164         """
    165         opts = ["hidl_hal_mode=%s" % self.hidl_hal_mode.encode("utf-8")];
    166         min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo()
    167         for i in range(max_cpu - min_cpu):
    168             self.web.AddProfilingDataUnlabeledVector(
    169                 "hwbinder_latency_%sbits" % bits,
    170                 result["fifo_%d_data" % i], options=opts,
    171                 x_axis_label="hwbinder latency",
    172                 y_axis_label="Frequency")
    173 
    174 
    175 if __name__ == "__main__":
    176     test_runner.main()
    177