46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
#!/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))
|