diff options
| -rwxr-xr-x | src/chattyparser.py | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/src/chattyparser.py b/src/chattyparser.py index d445528..4e4acae 100755 --- a/src/chattyparser.py +++ b/src/chattyparser.py @@ -1,5 +1,22 @@ #!/usr/bin/env python3 +# Copyright 2018-2019 Florian Fischer <florian.fl.fischer@fau.de> +# +# This file is part of allocbench. +# +# allocbench is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# allocbench is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with allocbench. If not, see <http://www.gnu.org/licenses/>. + """Parser and Plotter for the traces produced by chattymalloc""" import re @@ -94,7 +111,6 @@ def parse(path="chattymalloc.txt", coll_size=True, req_size=None, nohist=False): requested_size = [0] # Dictionary mapping allocation sizes to the count of their appearance hist = {} - line_count = 0 def record(ptr, size, optr=None, free=False): """Wrapper around record_allocation using local variables from parse""" @@ -102,8 +118,7 @@ def parse(path="chattymalloc.txt", coll_size=True, req_size=None, nohist=False): coll_size, req_size, nohist, optr, free) with open(path, "r") as trace_file: - for line in trace_file.readlines(): - line_count += 1 + for i, line in enumerate(trace_file.readlines()): valid_line = False for func, func_regex in TRACE_REGEX.items(): res = func_regex.match(line) @@ -124,12 +139,13 @@ def parse(path="chattymalloc.txt", coll_size=True, req_size=None, nohist=False): break if not valid_line: - print("\ninvalid line at", line_count, ":", line) + print(f"\ninvalid line at {i}: {line}") return hist, calls, np.array(requested_size) def plot(path): + """Plot a histogram and a memory profile of the given chattymalloc trace""" hist, calls, total_sizes = parse(path=path, req_size=None) plot_hist_ascii(f"{path}.hist", hist, calls) @@ -142,6 +158,7 @@ def plot(path): def plot_profile(total_sizes, trace_path, plot_path, sizes): + """Plot a memory profile of the total memory and the top 5 sizes""" x_vals = range(0, len(total_sizes)) plt.plot(x_vals, total_sizes / 1000, marker='', @@ -159,10 +176,11 @@ def plot_profile(total_sizes, trace_path, plot_path, sizes): plt.clf() def plot_hist_ascii(path, hist, calls): + """Plot an ascii histogram""" bins = {} for size in sorted(hist): - bin = int(size / 16) - bins[bin] = bins.get(bin, 0) + hist[size] + size_class = int(size / 16) + bins[size_class] = bins.get(size_class, 0) + hist[size] total = sum(calls.values()) - calls["free"] @@ -173,6 +191,10 @@ def plot_hist_ascii(path, hist, calls): print(file=hist_file) + print("Top 10 allocation sizes", file=hist_file) + for i, size in enumerate([t[1] for t in sorted([(n, s) for s, n in hist.items()])[-10:]]): + print(f"{i}. {size} B occurred {hist[size]} times", file=hist_file) + print("allocations <= 64", sum([n for s, n in hist.items() if s <= 64]), file=hist_file) print("allocations <= 1024", sum([n for s, n in hist.items() if s <= 1024]), file=hist_file) print("allocations <= 4096", sum([n for s, n in hist.items() if s <= 4096]), file=hist_file) @@ -191,6 +213,13 @@ def plot_hist_ascii(path, hist, calls): if __name__ == "__main__": + # Code duplication with src.util.print_license_and_exit + # to keep chattyparser independent from allocbench + if "--license" in sys.argv: + print("Copyright (C) 2018-2019 Florian Fischer") + print("License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>") + exit(0) + if len(sys.argv) != 2: print("chattyparser: parse chattymalloc output and", "create size histogram and memory profile", file=sys.stderr) |
