| #!/usr/bin/env python3 |
| # Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Visualizes the amount of IOSurface memory used over time. |
| """ |
| |
| import argparse |
| import time |
| |
| import matplotlib |
| from matplotlib import pylab as plt |
| import matplotlib.animation as animation |
| import numpy as np |
| |
| import parse_vmmap |
| |
| |
| def _PlotData(pid: int): |
| times = [] |
| virtual = [] |
| dirty = [] |
| swapped = [] |
| |
| fig = plt.figure(figsize=(16, 8)) |
| ax = fig.add_subplot(1, 1, 1) |
| first_time = time.time() |
| |
| def _Animate(i): |
| contents = parse_vmmap.ExecuteVmmap(pid) |
| io_surfaces = parse_vmmap.ParseIOSurface(contents, quiet=True) |
| total_virtual_size = sum(io_surface.size for io_surface in io_surfaces) |
| total_dirty_size = sum(io_surface.dirty for io_surface in io_surfaces) |
| total_swapped_size = sum(io_surface.swapped for io_surface in io_surfaces) |
| |
| print('SIZE = %d\tDIRTY = %d\tSWAPPED = %d' % |
| (total_virtual_size, total_dirty_size, total_swapped_size)) |
| now = time.time() |
| |
| times.append(now - first_time) |
| _MIB = 1 << 20 |
| virtual.append(total_virtual_size / _MIB) |
| dirty.append(total_dirty_size / _MIB) |
| swapped.append(total_swapped_size / _MIB) |
| bucket_sizes = [] |
| |
| ax.clear() |
| bottom = np.zeros(len(times)) |
| |
| top = np.array(swapped) |
| ax.plot(times, top, label='Swapped') |
| plt.fill_between(times, top, bottom) |
| bottom += swapped |
| |
| top += dirty |
| ax.plot(times, top, label='Dirty') |
| plt.fill_between(times, top, bottom) |
| bottom += dirty |
| |
| top = virtual |
| ax.plot(times, top, label='Virtual') |
| plt.fill_between(times, top, bottom) |
| |
| plt.ylim(bottom=0) |
| plt.xlim(left=times[0], right=times[-1]) |
| |
| plt.xlabel('Time (s)') |
| plt.ylabel('Memory (MiB)') |
| plt.title('IOSurface memory usage vs time - PID = %d' % pid) |
| |
| plt.legend() |
| |
| ani = animation.FuncAnimation(fig, _Animate, interval=1000) |
| plt.show() |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--pid', |
| help='PID of the GPU process', |
| type=int, |
| required=True) |
| args = parser.parse_args() |
| |
| _PlotData(args.pid) |
| |
| |
| if __name__ == '__main__': |
| main() |