File: plot_bucket_stats.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 (97 lines) | stat: -rwxr-xr-x 3,427 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
#!/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.
"""Plots the distribution of allocated and unallocated slots in SlotSpans.

To run this:
1. Build pa_tcache_inspect at a "close-enough" revision to the Chrome instance
   you're interested in.
2. Run pa_tcache_inspect --pid=PID_OF_RUNNING_CHROME_PROCESS --json=output.json
3. Run plot_bucket_stats.py --json=output.json --output=output.png
"""

import argparse
import json

import matplotlib
from matplotlib import pylab as plt
import numpy as np


def ParseJson(filename):
  with open(filename, 'r') as f:
    data = json.load(f)
  return data


def PlotData(data, output_filename):
  rows, cols = 6, 5
  fig, axs = plt.subplots(rows, cols, figsize=(30, 30))
  fig.suptitle('Active Slot Spans fill-in - %s' % output_filename, fontsize=16)
  for index, bucket in enumerate(data['buckets'][:rows * cols]):
    ax = axs[int(index / cols), index % cols]
    active_slot_spans = bucket['active_slot_spans']

    freelist_sizes = np.array([
        s['freelist_size'] if not s['is_decommitted'] else 0
        for s in active_slot_spans
    ])
    allocated_slots = np.array(
        [s['num_allocated_slots'] for s in active_slot_spans])
    unprovisioned_slots = np.array(
        [s['num_unprovisioned_slots'] for s in active_slot_spans])
    hatch = ['//' if s['freelist_is_sorted'] else '' for s in active_slot_spans]

    slot_size = bucket['slot_size']
    allocated_size = bucket['allocated_slots'] * slot_size
    free_size = bucket['freelist_size'] * slot_size
    ax.set_title('Slot span = %d\nAllocated size = %dkiB, Free size = %dkiB' %
                 (slot_size, allocated_size // 1024, free_size // 1024))
    indices = range(len(active_slot_spans))
    bottom = np.zeros(len(indices))
    b1 = ax.bar(indices, allocated_slots, bottom=bottom, color='green')
    bottom += allocated_slots
    b2 = ax.bar(indices,
                freelist_sizes,
                bottom=bottom,
                color=[
                    'darkgrey' if s['is_decommitted'] else 'red'
                    for s in active_slot_spans
                ],
                hatch=hatch)
    bottom += freelist_sizes
    ax.bar(indices, unprovisioned_slots, bottom=bottom, color='lightgrey')
    ax.set_xlim(left=-.5, right=len(indices) - .5)

  fig.tight_layout()
  fig.subplots_adjust(top=.95)
  handles = [
      matplotlib.patches.Patch(facecolor='green', label='Allocated'),
      matplotlib.patches.Patch(facecolor='red',
                               hatch='//',
                               label='Sorted freelist'),
      matplotlib.patches.Patch(facecolor='red', label='Free'),
      matplotlib.patches.Patch(facecolor='grey', label='Unprovisioned'),
      matplotlib.patches.Patch(facecolor='darkgrey', label='Decommitted')
  ]
  fig.legend(handles=handles, loc='lower right', fontsize=20)
  plt.savefig(output_filename)


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('--json',
                      help='JSON dump from pa_tcache_inspect',
                      required=True)
  parser.add_argument('--output_prefix',
                      help='Output file prefix',
                      required=True)

  args = parser.parse_args()
  data = ParseJson(args.json)
  PlotData(data, args.output_prefix)


if __name__ == '__main__':
  main()