Created
October 6, 2022 21:30
-
-
Save orip/4c7f7b552c629a89f9142c8de3290f3c to your computer and use it in GitHub Desktop.
Diff two runs of nm on similar executables to find large symbol size increases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
""" | |
Build to compare two outputs of this line on fairly identical executables | |
nm --print-size --radix=d <executable> | grep ' .* .* ' | cut -d' ' -f 2-10 | |
To just see the top symbols, can run e.g | |
nm --print-size --size-sort --radix=d <executable> | |
""" | |
from collections import Counter | |
import re | |
import subprocess | |
import sys | |
import textwrap | |
from typing import NamedTuple | |
class Diff(NamedTuple): | |
old_max: int | |
new_max: int | |
section: str | |
@property | |
def size(self): | |
return self.new_max - self.old_max | |
def get_diffs(): | |
diff = subprocess.run( | |
["diff", "-u0"] + sys.argv[1:], capture_output=True | |
).stdout.decode("utf-8") | |
# strip filenames | |
diff = diff[diff.index("@") :] | |
diff_sections = re.split(r"^@@.*@@$", diff, flags=re.MULTILINE) | |
def sizes_histogram(section, prefix): | |
return Counter( | |
int(line.split()[0].strip("-+")) | |
for line in section.splitlines() | |
if line.startswith(prefix) | |
) | |
for section in diff_sections: | |
section = section.strip() | |
pluses = sizes_histogram(section, prefix="+") | |
minuses = sizes_histogram(section, prefix="-") | |
if pluses == minuses: | |
# no change | |
continue | |
if not pluses or not minuses: | |
# not a diff | |
continue | |
# some sizes changed | |
yield Diff(section=section, old_max=max(minuses), new_max=max(pluses)) | |
def main(): | |
MB = 1048576 | |
big_diffs = sorted( | |
(x for x in get_diffs() if x.size > MB), key=lambda x: x.size, reverse=True | |
) | |
for diff in big_diffs[:20]: | |
print( | |
f""" | |
===== | |
{diff.size/1048576:.1f} MB increase | {100*diff.new_max/diff.old_max - 100:.1f}% | {diff.old_max} => {diff.new_max} | |
----- | |
{diff.section} | |
""".strip() | |
) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment