Get aggregated map usage

%3 cluster_00aa167e_48cb_449f_b8a0_9d2eb68aa2df Get aggregated map usage _24b643f3_1b4b_4c5b_98aa_63751088e3b0 Memory __0:cluster_00aa167e_48cb_449f_b8a0_9d2eb68aa2df->_24b643f3_1b4b_4c5b_98aa_63751088e3b0

This can be useful to get an idea of which modules are using more memory when loaded on a Python server. Just run it on a /proc/<pid>/maps file and take a look at the aggregated data.

#!/usr/bin/env python3

import sys

if len(sys.argv) != 2:
    print("Usage: {} <map file>".format(sys.argv[0]))
    exit(0)

with open(sys.argv[1], 'rt') as f:
    d = {}
    for line in f.readlines():
        chunks = line.split()
        if len(chunks) == 5:
            continue

        addrs, perm, off, dev, inode, mod = chunks
        low, high = map(lambda x: int(x, 16), addrs.split('-'))
        d[mod] = d.get(mod, 0) + int(high - low)
        d['total'] = d.get('total', 0) + int(high - low)

by_size = sorted([
    (sz, mod)
    for mod, sz in d.items()
], key=lambda x: x[0])

def to_mem(sz):
    if sz < (10 << 10):
        return f"{sz}b"
    if sz < (10 << 20):
        return f"{sz / (1 << 10):.2f}kb"
    if sz < (10 << 30):
        return f"{sz / (1 << 20):.2f}mb"
    return f"{sz / (1 << 30):.2f}gb"

for sz, mod in by_size:
    print(f"{to_mem(sz):9s}\t{mod}")