aboutsummaryrefslogtreecommitdiff
path: root/nm-data-to-csv.py
blob: ad890d785c70444ab303a85165a935e483da2da8 (plain)
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
#!/usr/bin/python3
import sys
import glob
import csv
import subprocess
import os
import metric_utils

"""
Parse output of nm -S -td."""

def get_symbol_size(symbol_to_size, exe_path):
    with open("nm_dump.txt", "w") as fp:
        subprocess.run(["nm", "-Std", exe_path], stdout=fp)

    with open("nm_dump.txt", 'r') as fp:
        lines = [line.strip() for line in fp.readlines()]
        for line in lines:
            components = line.split(" ")
            if len(components) == 4:
                size = int(components[1])
                section = components[2]
                symbol = components[3]

                # FIXME: Size is accumulated for static symbols in different
                # TU's having same name.
                if section.lower() == 't':
                    if symbol not in symbol_to_size:
                        symbol_to_size[symbol] = 0
                    symbol_to_size[symbol] += size

    return symbol_to_size

class Executable:
    def __init__(self, name, path):
        self.name = name
        self.path = path

    def calculate_size(self):
        return int(subprocess.check_output ("size {0} | tail -n1 | cut -f1".format(self.path), shell=True).decode('utf-8').strip())

def main():
    assert len(sys.argv) == 3
    results_dir = sys.argv[1]
    out_csv_file = sys.argv[2]

    outf = open(out_csv_file, "w")
    csvwriter = csv.writer(outf)
    csvwriter.writerow(("benchmark", "symbol", "size"))

    benchmarks = metric_utils.get_benchmarks_from_results_dir(results_dir)
    for bmk in benchmarks:
        exe_path = bmk.exe_path
        # Skip calculating size, if exe is not found.
        if exe_path is None:
            csvwriter.writerow((bmk.name, bmk.exe_name, 0))
            continue

        # exes holds the main exe and libs used by benchmark.
        exes = []
        exes.append(Executable(bmk.exe_name, exe_path))

        libs = bmk.libs
        for libname in libs.keys():
            exes.append(Executable(libname, libs[libname]))

        # FIXME: For now, accumulate size for symbols with same name across main exe and libraries.
        # So sym_to_size now contains symbols across the main exe and libs, with
        # one entry for common symbols.
        sym_to_size = {}
        for exe in exes:
            sym_to_size = get_symbol_size(sym_to_size, exe.path)

        # Write entry for libs: bmk, libname, total lib size
        for exe in exes:
            csvwriter.writerow((bmk.name, exe.name, exe.calculate_size()))

        # Write entry for indiviudal symbols
        for symbol in sym_to_size.keys():
            long_symbol = "[.] " + symbol
            size = sym_to_size[symbol]
            csvwriter.writerow((bmk.name, long_symbol, size))

    return 0

if __name__ == "__main__":
    exit(main())