| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| # | |
| # Analyse lock events and compute statistics | |
| # | |
| # Author: Alex Bennée <alex.bennee@linaro.org> | |
| # | |
| import simpletrace | |
| import argparse | |
| import numpy as np | |
| class MutexAnalyser(simpletrace.Analyzer): | |
| "A simpletrace Analyser for checking locks." | |
| def __init__(self): | |
| self.locks = 0 | |
| self.locked = 0 | |
| self.unlocks = 0 | |
| self.mutex_records = {} | |
| def _get_mutex(self, mutex): | |
| if not mutex in self.mutex_records: | |
| self.mutex_records[mutex] = {"locks": 0, | |
| "lock_time": 0, | |
| "acquire_times": [], | |
| "locked": 0, | |
| "locked_time": 0, | |
| "held_times": [], | |
| "unlocked": 0} | |
| return self.mutex_records[mutex] | |
| def qemu_mutex_lock(self, timestamp, mutex, filename, line): | |
| self.locks += 1 | |
| rec = self._get_mutex(mutex) | |
| rec["locks"] += 1 | |
| rec["lock_time"] = timestamp[0] | |
| rec["lock_loc"] = (filename, line) | |
| def qemu_mutex_locked(self, timestamp, mutex, filename, line): | |
| self.locked += 1 | |
| rec = self._get_mutex(mutex) | |
| rec["locked"] += 1 | |
| rec["locked_time"] = timestamp[0] | |
| acquire_time = rec["locked_time"] - rec["lock_time"] | |
| rec["locked_loc"] = (filename, line) | |
| rec["acquire_times"].append(acquire_time) | |
| def qemu_mutex_unlock(self, timestamp, mutex, filename, line): | |
| self.unlocks += 1 | |
| rec = self._get_mutex(mutex) | |
| rec["unlocked"] += 1 | |
| held_time = timestamp[0] - rec["locked_time"] | |
| rec["held_times"].append(held_time) | |
| rec["unlock_loc"] = (filename, line) | |
| def get_args(): | |
| "Grab options" | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--output", "-o", type=str, help="Render plot to file") | |
| parser.add_argument("events", type=str, help='trace file read from') | |
| parser.add_argument("tracefile", type=str, help='trace file read from') | |
| return parser.parse_args() | |
| if __name__ == '__main__': | |
| args = get_args() | |
| # Gather data from the trace | |
| analyser = MutexAnalyser() | |
| simpletrace.process(args.events, args.tracefile, analyser) | |
| print ("Total locks: %d, locked: %d, unlocked: %d" % | |
| (analyser.locks, analyser.locked, analyser.unlocks)) | |
| # Now dump the individual lock stats | |
| for key, val in sorted(analyser.mutex_records.items(), | |
| key=lambda k_v: k_v[1]["locks"]): | |
| print ("Lock: %#x locks: %d, locked: %d, unlocked: %d" % | |
| (key, val["locks"], val["locked"], val["unlocked"])) | |
| acquire_times = np.array(val["acquire_times"]) | |
| if len(acquire_times) > 0: | |
| print (" Acquire Time: min:%d median:%d avg:%.2f max:%d" % | |
| (acquire_times.min(), np.median(acquire_times), | |
| acquire_times.mean(), acquire_times.max())) | |
| held_times = np.array(val["held_times"]) | |
| if len(held_times) > 0: | |
| print (" Held Time: min:%d median:%d avg:%.2f max:%d" % | |
| (held_times.min(), np.median(held_times), | |
| held_times.mean(), held_times.max())) | |
| # Check if any locks still held | |
| if val["locks"] > val["locked"]: | |
| print (" LOCK HELD (%s:%s)" % (val["locked_loc"])) | |
| print (" BLOCKED (%s:%s)" % (val["lock_loc"])) |