diff options
| -rw-r--r-- | benchmark.py | 77 | ||||
| -rw-r--r-- | chattyparser.py | 102 |
2 files changed, 128 insertions, 51 deletions
diff --git a/benchmark.py b/benchmark.py index 365397f..1470c4f 100644 --- a/benchmark.py +++ b/benchmark.py @@ -157,18 +157,17 @@ class Benchmark (object): if nolibmemusage: try: - hist, calls, reqsize, top5reqsize = chattyparser.parse() - top5 = [s[1] for s in sorted([(n, s) for s, n in hist.items()])] - hist, calls, reqsize, top5reqsize = chattyparser.parse(track_top5=top5) - - chattyparser.plot_hist_ascii(hist, calls, file_name + ".hist") - chattyparser.plot_profile(reqsize, top5reqsize, file_name + ".profile.png") + chattyparser.plot() except MemoryError as memerr: print("Can't Analyse", actual_cmd, "with chattymalloc because", "to much memory would be needed.") continue + else: + with open(file_name + ".hist", "w") as f: + f.write(res.stderr) - os.environ["LD_PRELOAD"] = old_preload or "" + if nolibmemusage: + os.environ["LD_PRELOAD"] = old_preload or "" print() def run(self, verbose=False, runs=5): @@ -263,7 +262,7 @@ class Benchmark (object): for target in targets: y_vals = [] - for perm in self.iterate_args(): + for perm in self.iterate_args(args=args): d = [] for m in self.results[target][perm]: d.append(eval(yval.format(**m))) @@ -281,7 +280,7 @@ class Benchmark (object): plt.clf() def plot_fixed_arg(self, yval, ylabel="'y-label'", xlabel="loose_arg", - title="default title", filepostfix="", sumdir="", fixed=[]): + title="'default title'", filepostfix="", sumdir="", fixed=[]): args = self.results["args"] targets = self.results["targets"] @@ -308,3 +307,63 @@ class Benchmark (object): plt.savefig(os.path.join(sumdir, ".".join([self.name, arg, str(arg_value), filepostfix, "png"]))) plt.clf() + + def write_best_doublearg_tex_table(self, evaluation, sort=">", filepostfix="", sumdir="", std=False): + args = self.results["args"] + keys = list(args.keys()) + targets = self.results["targets"] + + header_arg = keys[0] if len(args[keys[0]]) < len(args[keys[1]]) else keys[1] + row_arg = [arg for arg in args if arg != header_arg][0] + + headers = args[header_arg] + print(header_arg, len(headers)) + rows = args[row_arg] + print(row_arg, len(rows)) + + cell_text = [] + for av in rows: + row = [] + for perm in self.iterate_args_fixed({row_arg: av}, args=args): + best = [] + best_val = None + for target in targets: + d = [] + for m in self.results[target][perm]: + d.append(eval(evaluation.format(**m))) + mean = np.mean(d) + if target == "glibc": + print(perm) + print(np.std(d)/mean, "%") + if perm.maxsize==64 and perm.nthreads==2: + print(target, mean) + if not best_val: + best = [target] + best_val = mean + elif (sort == ">" and mean > best_val) or (sort == "<" and mean < best_val): + + best = [target] + best_val = mean + elif mean == best_val: + best.append(target) + + row.append("{}: {:.3f}".format(best[0], best_val)) + cell_text.append(row) + + + fname = os.path.join(sumdir, ".".join([self.name, filepostfix, "tex"])) + with open(fname , "w") as f: + print("\\begin{tabular}{|", end="", file=f) + print(" l |" * len(headers),"}", file=f) + + print(header_arg+"/"+row_arg, end=" & ", file=f) + for header in headers[:-1]: + print(header, end="& ", file=f) + print(headers[-1], "\\\\", file=f) + + for i, row in enumerate(cell_text): + print(rows[i], end=" & ", file=f) + for e in row[:-1]: + print(e, end=" & ",file=f) + print(row[-1], "\\\\", file=f) + print("\\end{tabular}", file=f) diff --git a/chattyparser.py b/chattyparser.py index fc6975a..3406b44 100644 --- a/chattyparser.py +++ b/chattyparser.py @@ -11,7 +11,7 @@ calloc_re = re.compile("^c (?P<nmemb>\d+) {} {}$".format(size, ptr)) realloc_re = re.compile("^r {} {} {}$".format(ptr, size, ptr.replace("ptr", "nptr"))) memalign_re = re.compile("^mm (?P<alignment>\d+) {} {}$".format(size, ptr)) -def record_allocation(hist, total_size, top5, top5_sizes, allocations, ptr, size, optr=None, add=True): +def record_allocation(hist, total_size, allocations, ptr, size, coll_size, req_size, nohist, optr=None, add=True): size = int(size) if add: if optr and optr in allocations: @@ -19,33 +19,35 @@ def record_allocation(hist, total_size, top5, top5_sizes, allocations, ptr, size del(allocations[optr]) allocations[ptr] = size - hist[size] = hist.get(size, 0) + 1 + if not nohist: + hist[size] = hist.get(size, 0) + 1 if type(total_size[-1]) != int or type(size) != int: print("invalid type", type(total_size[-1]), type(size)) return - total_size.append(total_size[-1] + size) - for s in top5: - if s == size: - top5_sizes[s].append(top5_sizes[s][-1] + s) - else: - top5_sizes[s].append(top5_sizes[s][-1]) + + if coll_size: + if not req_size or size == req_size: + total_size.append(total_size[-1] + size) + elif req_size: + total_size.append(total_size[-1]) elif ptr != "(nil)" and ptr in allocations: size = allocations[ptr] - total_size.append(total_size[-1] - size) - for s in top5: - if s == size: - top5_sizes[s].append(top5_sizes[s][-1] - s) - else: - top5_sizes[s].append(top5_sizes[s][-1]) + if coll_size: + if not req_size or size == req_size: + total_size.append(total_size[-1] - size) + elif req_size: + total_size.append(total_size[-1]) + del(allocations[ptr]) + elif coll_size: + total_size.append(total_size[-1]) -def parse(path="chattymalloc.data", track_top5=[]): +def parse(path="chattymalloc.data", coll_size=True, req_size=None, nohist=False): tmalloc, tcalloc, trealloc, tfree, tmemalign= 0, 0, 0, 0, 0 allocations = {} requested_size = [0] - requested_size_top5 = {s: [0] for s in track_top5} hist = {} ln = 0 @@ -55,16 +57,16 @@ def parse(path="chattymalloc.data", track_top5=[]): res = malloc_re.match(l) if res != None: res = res.groupdict() - record_allocation(hist, requested_size, track_top5, requested_size_top5, - allocations, res["ptr"], res["size"]) + record_allocation(hist, requested_size, allocations, res["ptr"], + res["size"], coll_size, req_size, nohist) tmalloc += 1 continue res = free_re.match(l) if res != None: res = res.groupdict() - record_allocation(hist, requested_size, track_top5, requested_size_top5, - allocations, res["ptr"], 0, add=False) + record_allocation(hist, requested_size, allocations, res["ptr"], + 0, coll_size, req_size, nohist, add=False) tfree +=1 continue @@ -72,41 +74,50 @@ def parse(path="chattymalloc.data", track_top5=[]): if res != None: res = res.groupdict() size = int(res["nmemb"]) * int(res["size"]) - record_allocation(hist, requested_size, track_top5, requested_size_top5, - allocations, res["ptr"], size) + record_allocation(hist, requested_size, allocations, res["ptr"], + size, coll_size, req_size, nohist) tcalloc += 1 continue res = realloc_re.match(l) if res != None: res = res.groupdict() - record_allocation(hist, requested_size, track_top5, requested_size_top5, - allocations, res["nptr"], res["size"], optr=res["ptr"]) + record_allocation(hist, requested_size, allocations, res["nptr"], + res["size"], coll_size, req_size, nohist, optr=res["ptr"]) trealloc += 1 continue res = memalign_re.match(l) if res != None: res = res.groupdict() - record_allocation(hist, requested_size, track_top5, requested_size_top5, - allocations, res["ptr"], res["size"]) + record_allocation(hist, requested_size, allocations, res["ptr"], + res["size"], coll_size, req_size, nohist) tmemalign += 1 continue print("\ninvalid line at", ln, ":", l) calls = {"malloc": tmalloc, "free": tfree, "calloc": tcalloc, "realloc": trealloc, "memalign": tmemalign} - return hist, calls, requested_size, requested_size_top5 + return hist, calls, requested_size + +def plot(path): + hist, calls, _ = parse(req_size=None) + plot_hist_ascii(path+".hist", hist, calls) + top5 = [t[1] for t in sorted([(n, s) for s, n in hist.items()])[-5:]] -def hist(path="chattymalloc.data"): - return parse(path=path)[0] + del(hist) + del(calls) + plot_profile(path+".profile.png", top5) -def plot_profile(total_size, total_top5, path): - x_vals = list(range(0, len(total_size))) + +def plot_profile(path, top5): + _, calls, total_size = parse(nohist=True) + x_vals = range(0, sum(calls.values()) + 1) plt.plot(x_vals, total_size, marker='', linestyle='-', label="Total requested") - for top5 in total_top5: - plt.plot(x_vals, total_top5[top5], label=top5) + for s in top5: + _, calls, total_size = parse(nohist=True, req_size=s) + plt.plot(x_vals, total_size, label=s) plt.legend() plt.xlabel("Allocations") @@ -115,16 +126,13 @@ def plot_profile(total_size, total_top5, path): plt.savefig(path) plt.clf() - -def plot_hist_ascii(hist, calls, path): +def plot_hist_ascii(path, hist, calls): bins = {} - bin = 1 for size in sorted(hist): - if int(size) > bin * 16: - bin += 1 + bin = int(size / 16) bins[bin] = bins.get(bin, 0) + hist[size] - total = sum(calls.values()) + total = sum(calls.values()) - calls["free"] with open(path, "w") as f: print("Total function calls:", total, file=f) print("malloc:", calls["malloc"], file=f) @@ -132,9 +140,19 @@ def plot_hist_ascii(hist, calls, path): print("realloc:", calls["realloc"], file=f) print("free:", calls["free"], file=f) print("memalign:", calls["memalign"], file=f) + print(file=f) + + print("< 1024", sum([n for s,n in hist.items() if s < 1024]), file=f) + print("< 4096", sum([n for s,n in hist.items() if s < 4096]), file=f) + print(file=f) print("Histogram of sizes:", file=f) - for b in sorted(bins): + sbins = sorted(bins) + binmaxlength = str(len(str(sbins[-1])) + 1) + amountmaxlength = str(len(str(sorted(bins.values())[-1]))) + for b in sbins: perc = bins[b]/total*100 - hist_line = "{} - {}\t{}\t{:.2}% {}" - print(hist_line.format((b-1)*16, b*16-1, bins[b], perc, '*'*int(perc/2)), file=f) + binsize = "{:<" + binmaxlength + "} - {:>" + binmaxlength + "}" + print(binsize.format((b)*16, (b+1)*16-1), end=" ", file=f) + amount = "{:<" + amountmaxlength + "} {:.2f}% {}" + print(amount.format(bins[b], perc, '*'*int(perc/2)), file=f) |
