File: pa_graph_buckets.py

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (99 lines) | stat: -rw-r--r-- 3,171 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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.
"""
This script allows us to create a live graph of internal fragmentation in
Chrome, updated as chrome runs.

Usage:
  1. Compile chrome with the RECORD_ALLOC_INFO flag.
  2. Compile pa_bucket_inspect tool with the RECORD_ALLOC_INFO flag.
  3. Start Chrome.
  4. Find the PID of the process you wish to create graphs for.
  5. run pa_bucket_inspect <PID>
  6. run this script.
"""

from sys import argv
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches


def main(argv: list[str]) -> None:
  DUMPNAME: final = "dump.dat"
  KIB: final = 1024
  MIB: final = KIB * 1024

  fig, axes = plt.subplots(2, 1)
  (ax_a, ax_b) = axes
  axes = ax_a, ax_b, ax_c, ax_d

  green_patch = mpatches.Patch(color='g', label='Used')
  plum_patch = mpatches.Patch(color='plum', label='Wasted')

  def animate(i):
    bucket_sizes = []
    x = []
    ya1 = []
    ya2 = []
    yb1 = []
    yb2 = []
    with open(DUMPNAME, 'r') as f:
      for line in f.readlines():
        index, bucket_size, num_allocs_a, total_requested_size_a, num_allocs_b, total_requested_size_b = [
            int(tmp) for tmp in line.strip().split(',')
        ]

        def record_allocs_and_sizes(y1, y2, num_allocs, total_requested_size):
          y1.append(bucket_size * num_allocs / MIB)
          y2.append((bucket_size * num_allocs - total_requested_size) / MIB)

        print(index, bucket_size, num_allocs_a, total_requested_size_a,
              num_allocs_b, total_requested_size_b)
        x.append((index))

        # format buckets sizes with commas, e.g. 50000 -> 50,000
        bucket_sizes.append('{:,}'.format(bucket_size))

        record_allocs_and_sizes(ya1, ya2, num_allocs_a, total_requested_size_a)
        record_allocs_and_sizes(yb1, yb2, num_allocs_b, total_requested_size_b)

    total_size_a = sum(ya1)
    total_size_b = sum(yb1)

    def plot_buckets(ax, x, y1, y2):
      ax.clear()
      ax.set_xticks(x, bucket_sizes, rotation='vertical')
      ax.set_xlabel('Bucket Size (B)')
      ax.set_ylabel('Total Memory Usage (MiB)')
      ax.bar(x, y1, color='g', width=0.8)
      ax.bar(x, y2, bottom=y1, color='plum', width=0.8)
      ax.legend(handles=[green_patch, plum_patch])

    plot_buckets(ax_a, x, ya1, ya2)
    plot_buckets(ax_b, x, yb1, yb2)

    # We want both plots to use the same y-height, so they can be compared
    # easily just by looking at them.
    h = max(ax.get_ylim() for ax in axes)
    for ax in axes:
      plt.setp(ax, ylim=h)

    def show_title(ax, total_size):
      diff = total_size - total_size_a
      ax.set_title(
          'Alternate Distribution uses an extra {:+.2f} KiB due to internal fragmentation ({:+.2%})'
          .format(diff * KIB, diff / total_size_a),
          size='medium')

    plt.suptitle('Memory Usage v. Bucket Size', size='x-large', weight='bold')
    show_title(ax_b, total_size_b)

  ani = animation.FuncAnimation(fig, animate, interval=1000)
  plt.tight_layout()
  plt.show()


if __name__ == '__main__':
  main(argv)