1#!/usr/bin/env python3 2# 3# Copyright (C) 2018 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 18import os 19import statistics 20import subprocess 21import sys 22import tempfile 23import time 24 25# Make sure environment is setup, otherwise "adb" module is not available. 26if os.getenv("ANDROID_BUILD_TOP") is None: 27 print("Run source/lunch before running " + sys.argv[0]) 28 sys.exit() 29 30import adb 31 32def lock_min(device): 33 device.shell_nocheck([""" 34 for x in /sys/devices/system/cpu/cpu?/cpufreq; do 35 echo userspace > $x/scaling_governor 36 cat $x/scaling_min_freq > $x/scaling_setspeed 37 done 38 """]) 39 40def lock_max(device): 41 device.shell_nocheck([""" 42 for x in /sys/devices/system/cpu/cpu?/cpufreq; do 43 echo userspace > $x/scaling_governor 44 cat $x/scaling_max_freq > $x/scaling_setspeed 45 done 46 """]) 47 48def unlock(device): 49 device.shell_nocheck([""" 50 for x in /sys/devices/system/cpu/cpu?/cpufreq; do 51 echo ondemand > $x/scaling_governor 52 echo sched > $x/scaling_governor 53 echo schedutil > $x/scaling_governor 54 done 55 """]) 56 57def harmonic_mean(xs): 58 return 1.0 / statistics.mean([1.0 / x for x in xs]) 59 60def analyze(name, speeds): 61 median = statistics.median(speeds) 62 mean = harmonic_mean(speeds) 63 stddev = statistics.stdev(speeds) 64 msg = "%s: %d runs: median %.2f MiB/s, mean %.2f MiB/s, stddev: %.2f MiB/s" 65 print(msg % (name, len(speeds), median, mean, stddev)) 66 67def benchmark_sink(device=None, size_mb=100): 68 if device == None: 69 device = adb.get_device() 70 71 speeds = list() 72 cmd = device.adb_cmd + ["raw", "sink:%d" % (size_mb * 1024 * 1024)] 73 74 with tempfile.TemporaryFile() as tmpfile: 75 tmpfile.truncate(size_mb * 1024 * 1024) 76 77 for _ in range(0, 10): 78 tmpfile.seek(0) 79 begin = time.time() 80 subprocess.check_call(cmd, stdin=tmpfile) 81 end = time.time() 82 speeds.append(size_mb / float(end - begin)) 83 84 analyze("sink %dMiB" % size_mb, speeds) 85 86def benchmark_source(device=None, size_mb=100): 87 if device == None: 88 device = adb.get_device() 89 90 speeds = list() 91 cmd = device.adb_cmd + ["raw", "source:%d" % (size_mb * 1024 * 1024)] 92 93 with open(os.devnull, 'w') as devnull: 94 for _ in range(0, 10): 95 begin = time.time() 96 subprocess.check_call(cmd, stdout=devnull) 97 end = time.time() 98 speeds.append(size_mb / float(end - begin)) 99 100 analyze("source %dMiB" % size_mb, speeds) 101 102def benchmark_push(device=None, file_size_mb=100): 103 if device == None: 104 device = adb.get_device() 105 106 remote_path = "/dev/null" 107 local_path = "/tmp/adb_benchmark_temp" 108 109 with open(local_path, "wb") as f: 110 f.truncate(file_size_mb * 1024 * 1024) 111 112 speeds = list() 113 for _ in range(0, 10): 114 begin = time.time() 115 device.push(local=local_path, remote=remote_path) 116 end = time.time() 117 speeds.append(file_size_mb / float(end - begin)) 118 119 analyze("push %dMiB" % file_size_mb, speeds) 120 121def benchmark_pull(device=None, file_size_mb=100): 122 if device == None: 123 device = adb.get_device() 124 125 remote_path = "/data/local/tmp/adb_benchmark_temp" 126 local_path = "/tmp/adb_benchmark_temp" 127 128 device.shell(["dd", "if=/dev/zero", "of=" + remote_path, "bs=1m", 129 "count=" + str(file_size_mb)]) 130 speeds = list() 131 for _ in range(0, 10): 132 begin = time.time() 133 device.pull(remote=remote_path, local=local_path) 134 end = time.time() 135 speeds.append(file_size_mb / float(end - begin)) 136 137 analyze("pull %dMiB" % file_size_mb, speeds) 138 139def benchmark_shell(device=None, file_size_mb=100): 140 if device == None: 141 device = adb.get_device() 142 143 speeds = list() 144 for _ in range(0, 10): 145 begin = time.time() 146 device.shell(["dd", "if=/dev/zero", "bs=1m", 147 "count=" + str(file_size_mb)]) 148 end = time.time() 149 speeds.append(file_size_mb / float(end - begin)) 150 151 analyze("shell %dMiB" % file_size_mb, speeds) 152 153def main(): 154 device = adb.get_device() 155 unlock(device) 156 benchmark_sink(device) 157 benchmark_source(device) 158 benchmark_push(device) 159 benchmark_pull(device) 160 161if __name__ == "__main__": 162 main() 163