#!/usr/bin/env python3 """Emit mapping-category totals without path names from local Linux /proc/PID/smaps.""" import argparse from collections import defaultdict import json from pathlib import Path import re HEADER = re.compile(r"^[0-9a-f]+-[0-9a-f]+\s+(\S+)\s+\S+\s+\S+\s+\S+\s*(.*)$") METRIC = re.compile(r"^(Size|Rss|Pss|Private_Dirty|Private_Clean|Anonymous):\s+(\d+) kB$") def summarize(path): groups = defaultdict(lambda: defaultdict(int)) group = None for line in path.read_text().splitlines(): header = HEADER.match(line) if header: permissions, name = header.groups() if "doublemapper" in name: group = "jit-doublemapper" elif name == "[heap]": group = "native-heap" elif name.startswith("[stack"): group = "stack" elif not name: group = "anonymous-exec" if "x" in permissions else "anonymous-write" if "w" in permissions else "anonymous-read" elif name.endswith(".dll"): group = "managed-assembly-files" elif ".so" in name: group = "native-library-files" elif name.startswith("["): group = "other-kernel-mappings" else: group = "other-files" elif group and (metric := METRIC.match(line)): groups[group][metric[1]] += int(metric[2]) * 1024 return dict(groups) if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("files", nargs="+", type=Path) args = parser.parse_args() print(json.dumps([{"sample": index, "groups": summarize(path)} for index, path in enumerate(args.files)], indent=2))