diff options
| author | Florian Fischer <florian.fl.fischer@fau.de> | 2020-05-11 14:30:39 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fl.fischer@fau.de> | 2020-06-02 11:18:47 +0200 |
| commit | ffacbbece6af0f84d4bc7c8c4365797e8a433ef7 (patch) | |
| tree | 57ad32954b0e3903b3c9472090f2f414efd8dfc5 | |
| parent | f2ebd50f099af160bc39584afa95f812215630d1 (diff) | |
| download | allocbench-ffacbbece6af0f84d4bc7c8c4365797e8a433ef7.tar.gz allocbench-ffacbbece6af0f84d4bc7c8c4365797e8a433ef7.zip | |
format the source code using yapf
| -rw-r--r-- | allocbench/allocator.py | 29 | ||||
| -rw-r--r-- | allocbench/allocators/mimalloc.py | 1 | ||||
| -rw-r--r-- | allocbench/allocators/scalloc.py | 3 | ||||
| -rw-r--r-- | allocbench/allocators/tcmalloc.py | 5 | ||||
| -rw-r--r-- | allocbench/artifact.py | 15 | ||||
| -rw-r--r-- | allocbench/benchmark.py | 14 | ||||
| -rw-r--r-- | allocbench/benchmarks/dj_trace.py | 2 | ||||
| -rw-r--r-- | allocbench/benchmarks/espresso.py | 3 | ||||
| -rw-r--r-- | allocbench/benchmarks/httpd.py | 2 | ||||
| -rw-r--r-- | allocbench/benchmarks/keydb.py | 5 | ||||
| -rw-r--r-- | allocbench/benchmarks/larson.py | 2 | ||||
| -rw-r--r-- | allocbench/benchmarks/loop.py | 62 | ||||
| -rw-r--r-- | allocbench/benchmarks/mysql.py | 9 | ||||
| -rw-r--r-- | allocbench/benchmarks/raxmlng.py | 2 | ||||
| -rw-r--r-- | allocbench/benchmarks/rdtsc.py | 2 | ||||
| -rw-r--r-- | allocbench/facter.py | 4 | ||||
| -rw-r--r-- | allocbench/globalvars.py | 11 | ||||
| -rw-r--r-- | allocbench/plots.py | 77 | ||||
| -rw-r--r-- | allocbench/util.py | 2 | ||||
| -rwxr-xr-x | merge.py | 38 | ||||
| -rwxr-xr-x | scripts/histogram.py | 27 | ||||
| -rwxr-xr-x | scripts/paper_plots.py | 87 | ||||
| -rwxr-xr-x | scripts/print_facts.py | 10 |
23 files changed, 265 insertions, 147 deletions
diff --git a/allocbench/allocator.py b/allocbench/allocator.py index 0eefce2..cbeee06 100644 --- a/allocbench/allocator.py +++ b/allocbench/allocator.py @@ -98,14 +98,17 @@ class Allocator: patch_content = patch_file.read() # check if patch is already applied - not_patched = run_cmd( - ["patch", "-R", "-p0", "-s", "-f", "--dry-run", "--verbose"], - cwd=cwd, - input=patch_content, - check=False).returncode + not_patched = run_cmd([ + "patch", "-R", "-p0", "-s", "-f", "--dry-run", "--verbose" + ], + cwd=cwd, + input=patch_content, + check=False).returncode if not_patched: try: - run_cmd(["patch", "-p0", "--verbose"], cwd=cwd, input=patch_content) + run_cmd(["patch", "-p0", "--verbose"], + cwd=cwd, + input=patch_content) except CalledProcessError as err: print_debug(err.stderr, file=sys.stderr) print_error(f"Patching of {self.name} failed.") @@ -180,6 +183,7 @@ class Allocator: print_debug("Resulting dictionary:", res_dict) return res_dict + def collect_installed_allocators(): """Collect allocators using installed system libraries""" @@ -214,6 +218,7 @@ def collect_installed_allocators(): return allocators + def collect_available_allocators(): """Collect all allocator definitions shipped with allocbench""" @@ -228,6 +233,7 @@ def collect_available_allocators(): return available_allocators + def read_allocators_collection_file(alloc_path): """Read and evaluate a python file looking for an exported dict called allocators""" @@ -276,11 +282,16 @@ def collect_allocators(allocators): # interpret name as allocator name or wildcard else: - matched_allocators = fnmatch.filter(available_allocators.keys(), name) + matched_allocators = fnmatch.filter(available_allocators.keys(), + name) if matched_allocators: - ret.update({a: available_allocators[a].build() for a in matched_allocators}) + ret.update({ + a: available_allocators[a].build() + for a in matched_allocators + }) else: print_error( name, - "is neither a python file or a known allocator definition.") + "is neither a python file or a known allocator definition." + ) return ret diff --git a/allocbench/allocators/mimalloc.py b/allocbench/allocators/mimalloc.py index c6952c5..8f8f1ff 100644 --- a/allocbench/allocators/mimalloc.py +++ b/allocbench/allocators/mimalloc.py @@ -34,5 +34,6 @@ class Mimalloc(Allocator): super().__init__(name, **kwargs) + # pylint: disable=invalid-name mimalloc = Mimalloc("mimalloc", version="v1.6.0") diff --git a/allocbench/allocators/scalloc.py b/allocbench/allocators/scalloc.py index d009226..4541a03 100644 --- a/allocbench/allocators/scalloc.py +++ b/allocbench/allocators/scalloc.py @@ -42,7 +42,8 @@ class Scalloc(Allocator): super().__init__(name, **kwargs) def build(self): - with open("/proc/sys/vm/overcommit_memory", "r") as overcommit_memory_file: + with open("/proc/sys/vm/overcommit_memory", + "r") as overcommit_memory_file: if overcommit_memory_file.read()[0] != "1": raise AssertionError("""\ vm.overcommit_memory not set diff --git a/allocbench/allocators/tcmalloc.py b/allocbench/allocators/tcmalloc.py index 450b613..2c026a5 100644 --- a/allocbench/allocators/tcmalloc.py +++ b/allocbench/allocators/tcmalloc.py @@ -84,8 +84,9 @@ tcmalloc_gperftools_align = TCMallocGperftools("TCMalloc-Gperftools-Aligned", version="gperftools-2.7", color="xkcd:navy blue") -tcmalloc_gperftools_align.ld_preload = (f"{BUILDDIR}/align_to_cl.so " - f"{tcmalloc_gperftools_align.ld_preload}") +tcmalloc_gperftools_align.ld_preload = ( + f"{BUILDDIR}/align_to_cl.so " + f"{tcmalloc_gperftools_align.ld_preload}") tcmalloc_gperftools_cacheline_exclusive = TCMallocGperftools( "TCMalloc-Gperftools-Cacheline-Exclusive", diff --git a/allocbench/artifact.py b/allocbench/artifact.py index 3504486..28b82aa 100644 --- a/allocbench/artifact.py +++ b/allocbench/artifact.py @@ -72,12 +72,16 @@ class GitArtifact(Artifact): # check if we have already provided this checkout if os.path.exists(location): try: - run_cmd(["git", "fetch", "--force"], output_verbosity=1, cwd=location) + run_cmd(["git", "fetch", "--force"], + output_verbosity=1, + cwd=location) except CalledProcessError: print_error(f"Failed to update {location}") raise try: - run_cmd(["git", "reset", "--hard", checkout], output_verbosity=1, cwd=location) + run_cmd(["git", "reset", "--hard", checkout], + output_verbosity=1, + cwd=location) except CalledProcessError: print_error(f"Failed to update {location}") raise @@ -90,7 +94,9 @@ class GitArtifact(Artifact): # update repo print_status(f'Updating git repository "{self.name}" ...') try: - run_cmd(["git", "fetch", "--force"], output_verbosity=1, cwd=self.repo) + run_cmd(["git", "fetch", "--force"], + output_verbosity=1, + cwd=self.repo) except CalledProcessError: print_error(f"Failed to update {self.name}") raise @@ -125,7 +131,8 @@ class ArchiveArtifact(Artifact): f'Archive format "{format}" not in supported list {self.supported_formats}' ) self.archive_format = archive_format - self.archive = os.path.join(self.basedir, f"{self.name}.{self.archive_format}") + self.archive = os.path.join(self.basedir, + f"{self.name}.{self.archive_format}") self.checksum = checksum def retrieve(self): diff --git a/allocbench/benchmark.py b/allocbench/benchmark.py index 6a2e7f2..afcb126 100644 --- a/allocbench/benchmark.py +++ b/allocbench/benchmark.py @@ -547,8 +547,10 @@ class Benchmark: # Preallocator hook if hasattr(self, "preallocator_hook"): - self.preallocator_hook((alloc_name, alloc), run, # pylint: disable=no-member - os.environ) + self.preallocator_hook( + (alloc_name, alloc), + run, # pylint: disable=no-member + os.environ) # Run benchmark for alloc for perm in self.iterate_args(): @@ -637,12 +639,8 @@ class Benchmark: result, res.stderr, alloc_name, perm) if hasattr(self, "process_output"): # pylint: disable=no-member - self.process_output( - result, - res.stdout, - res.stderr, - alloc_name, - perm) + self.process_output(result, res.stdout, res.stderr, + alloc_name, perm) # save a valid result so we can expand invalid ones if valid_result is None: diff --git a/allocbench/benchmarks/dj_trace.py b/allocbench/benchmarks/dj_trace.py index 09adcd4..e96ab5d 100644 --- a/allocbench/benchmarks/dj_trace.py +++ b/allocbench/benchmarks/dj_trace.py @@ -385,7 +385,7 @@ class BenchmarkDJTrace(Benchmark): for perm in self.iterate_args(args=args): cycles = abplt.get_y_data(self, "{cycles}", allocator, - perm)[0] + perm)[0] times = func_times_means[allocator][perm] rss = rss_means[allocator][perm] print(fmt.format(perm.workload, cycles, times[0], times[1], diff --git a/allocbench/benchmarks/espresso.py b/allocbench/benchmarks/espresso.py index 0b9b852..7960286 100644 --- a/allocbench/benchmarks/espresso.py +++ b/allocbench/benchmarks/espresso.py @@ -69,8 +69,7 @@ class BenchmarkEspresso(Benchmark): self.cmd = "espresso{binary_suffix} {file}" self.args = { - "file": - [os.path.join(BENCHSRCDIR, name, "largest.espresso")] + "file": [os.path.join(BENCHSRCDIR, name, "largest.espresso")] } self.requirements = ["espresso"] diff --git a/allocbench/benchmarks/httpd.py b/allocbench/benchmarks/httpd.py index a601612..ac06459 100644 --- a/allocbench/benchmarks/httpd.py +++ b/allocbench/benchmarks/httpd.py @@ -50,7 +50,7 @@ class BenchmarkHTTPD(Benchmark): "ab", "-V") @staticmethod - def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument result["time"] = re.search( "Time taken for tests:\\s*(\\d*\\.\\d*) seconds", stdout).group(1) result["requests"] = re.search( diff --git a/allocbench/benchmarks/keydb.py b/allocbench/benchmarks/keydb.py index 1cb6e64..3aeb6f1 100644 --- a/allocbench/benchmarks/keydb.py +++ b/allocbench/benchmarks/keydb.py @@ -53,7 +53,8 @@ class BenchmarkKeyDB(Benchmark): keydb_dir = os.path.join(self.build_dir, "keydb") if not os.path.exists(os.path.join(self.build_dir, "keydb-server")): - keydb_artifact = GitArtifact("keydb", "https://github.com/JohnSully/KeyDB") + keydb_artifact = GitArtifact("keydb", + "https://github.com/JohnSully/KeyDB") os.makedirs(self.build_dir, exist_ok=True) @@ -92,7 +93,7 @@ class BenchmarkKeyDB(Benchmark): os.link(src, dest) @staticmethod - def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument cmds = ["Sets", "Gets", "Waits", "Totals"] stats = ["ops", "hits", "misses", "latency", "throughput"] for line in stdout.splitlines(): diff --git a/allocbench/benchmarks/larson.py b/allocbench/benchmarks/larson.py index cc78be7..0d25126 100644 --- a/allocbench/benchmarks/larson.py +++ b/allocbench/benchmarks/larson.py @@ -72,7 +72,7 @@ class BenchmarkLarson(Benchmark): super().__init__(name) @staticmethod - def process_output(result, stdout, stderr, target, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, target, perm): # pylint: disable=too-many-arguments, unused-argument for line in stdout.splitlines(): res = THROUGHPUT_RE.match(line) if res: diff --git a/allocbench/benchmarks/loop.py b/allocbench/benchmarks/loop.py index 1c22da8..ae7d36b 100644 --- a/allocbench/benchmarks/loop.py +++ b/allocbench/benchmarks/loop.py @@ -57,53 +57,49 @@ class BenchmarkLoop(Benchmark): super().__init__(name) @staticmethod - def process_output(result, stdout, stderr, alloc, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, alloc, perm): # pylint: disable=too-many-arguments, unused-argument result["mops"] = perm.threads / float(result["task-clock"]) def summary(self): # Speed - plt.plot( - self, - "{mops}", - fig_options={ - 'ylabel': 'MOPS/cpu-second', - 'title': 'Loop: {fixed_part_str}', - 'autoticks': False, - }, - file_postfix="time") + plt.plot(self, + "{mops}", + fig_options={ + 'ylabel': 'MOPS/cpu-second', + 'title': 'Loop: {fixed_part_str}', + 'autoticks': False, + }, + file_postfix="time") # L1 cache misses - plt.plot( - self, - "({L1-dcache-load-misses}/{L1-dcache-loads})*100", - fig_options={ - 'ylabel': "L1 misses in %", - 'title': "Loop l1 cache misses: {fixed_part_str}", - 'autoticks': False, - }, - file_postfix="l1misses") + plt.plot(self, + "({L1-dcache-load-misses}/{L1-dcache-loads})*100", + fig_options={ + 'ylabel': "L1 misses in %", + 'title': "Loop l1 cache misses: {fixed_part_str}", + 'autoticks': False, + }, + file_postfix="l1misses") # Speed Matrix - plt.write_best_doublearg_tex_table( - self, - "{mops}", - file_postfix="time.matrix") - - plt.write_tex_table( - self, - [{ - "label": "MOPS/s", - "expression": "{mops}", - "sort": ">" - }], - file_postfix="mops.table") + plt.write_best_doublearg_tex_table(self, + "{mops}", + file_postfix="time.matrix") + + plt.write_tex_table(self, [{ + "label": "MOPS/s", + "expression": "{mops}", + "sort": ">" + }], + file_postfix="mops.table") plt.export_stats_to_csv(self, "task-clock") plt.export_stats_to_dataref(self, "task-clock") # pgfplot test plt.pgfplot(self, - self.iterate_args(fixed={"maxsize": 1024}, args=self.results["args"]), + self.iterate_args(fixed={"maxsize": 1024}, + args=self.results["args"]), "int(perm.threads)", "{mops}", xlabel="Threads", diff --git a/allocbench/benchmarks/mysql.py b/allocbench/benchmarks/mysql.py index 111d482..611405d 100644 --- a/allocbench/benchmarks/mysql.py +++ b/allocbench/benchmarks/mysql.py @@ -185,7 +185,7 @@ class BenchmarkMYSQL(Benchmark): shutil.rmtree(self.build_dir, ignore_errors=True) @staticmethod - def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument result["transactions"] = re.search("transactions:\\s*(\\d*)", stdout).group(1) result["queries"] = re.search("queries:\\s*(\\d*)", stdout).group(1) @@ -294,7 +294,8 @@ class BenchmarkMYSQL(Benchmark): fname = ".".join([self.name, "transactions.tex"]) headers = [perm.nthreads for perm in self.iterate_args(args=args)] with open(fname, "w") as table_file: - print("\\begin{tabular}{| l" + " l" * len(headers) + " |}", file=table_file) + print("\\begin{tabular}{| l" + " l" * len(headers) + " |}", + file=table_file) print("Fäden / Allokator ", end=" ", file=table_file) for head in headers: print("& {}".format(head), end=" ", file=table_file) @@ -311,7 +312,9 @@ class BenchmarkMYSQL(Benchmark): color = "red" else: color = "black" - print(entry_string.format(color, mean), end=" ", file=table_file) + print(entry_string.format(color, mean), + end=" ", + file=table_file) print("\\\\", file=table_file) print("\\end{tabular}", file=table_file) diff --git a/allocbench/benchmarks/raxmlng.py b/allocbench/benchmarks/raxmlng.py index b943e4e..be2a080 100644 --- a/allocbench/benchmarks/raxmlng.py +++ b/allocbench/benchmarks/raxmlng.py @@ -76,7 +76,7 @@ class BenchmarkRaxmlng(Benchmark): os.remove(direntry) @staticmethod - def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument, no-self-use + def process_output(result, stdout, stderr, allocator, perm): # pylint: disable=too-many-arguments, unused-argument, no-self-use result["runtime"] = RUNTIME_RE.search(stdout).group("runtime") def summary(self): diff --git a/allocbench/benchmarks/rdtsc.py b/allocbench/benchmarks/rdtsc.py index 0600f4c..4414d49 100644 --- a/allocbench/benchmarks/rdtsc.py +++ b/allocbench/benchmarks/rdtsc.py @@ -47,7 +47,7 @@ class BenchmarkRdtsc(Benchmark): super().__init__(name) @staticmethod - def process_output(result, stdout, stderr, alloc, perm): # pylint: disable=too-many-arguments, unused-argument + def process_output(result, stdout, stderr, alloc, perm): # pylint: disable=too-many-arguments, unused-argument all_cycles = [] for line in stdout.splitlines(): all_cycles.append(int(line.split()[1])) diff --git a/allocbench/facter.py b/allocbench/facter.py index 57f5abd..afc1d02 100644 --- a/allocbench/facter.py +++ b/allocbench/facter.py @@ -30,6 +30,7 @@ from allocbench.util import print_debug, print_info, print_warn, run_cmd FACTS = {} + def collect_facts(): """Collect general facts about the benchmark environment""" # Populate allocbench.globalvars.facts on import @@ -93,8 +94,9 @@ def load_facts(path=None): print_info(f"Loading facts from: {filename}") + def allocbench_version(): - "Store and return allocbench version string.""" + """Store and return allocbench version string.""" if "allocbench" in FACTS: return FACTS["allocbench"] diff --git a/allocbench/globalvars.py b/allocbench/globalvars.py index bb41dad..f2a98f0 100644 --- a/allocbench/globalvars.py +++ b/allocbench/globalvars.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with allocbench. If not, see <http://www.gnu.org/licenses/>. - """Global variables for allocbench VERBOSITY: Verbosity level -1: quiet, 0: status, 1: info, 2: stdout of subcommands, 3: debug info @@ -33,13 +32,13 @@ RESDIR: Directory were the benchmark results are stored import inspect import os - VERBOSITY = 0 ALLOCATORS = {} # /.../allocbench/allocbench -SRCDIR = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +SRCDIR = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) # /.../allocbench/allocbench/benchmarks BENCHSRCDIR = os.path.join(SRCDIR, "benchmarks") @@ -58,8 +57,10 @@ ALLOCBUILDDIR = os.path.join(BUILDDIR, "allocators") RESDIR = None -BENCHMARKS = [e[:-3] for e in os.listdir(os.path.join(ALLOCBENCHDIR, BENCHSRCDIR)) - if e[-3:] == ".py" and e != "__init__.py"] +BENCHMARKS = [ + e[:-3] for e in os.listdir(os.path.join(ALLOCBENCHDIR, BENCHSRCDIR)) + if e[-3:] == ".py" and e != "__init__.py" +] SUMMARY_FILE_EXT = "svg" diff --git a/allocbench/plots.py b/allocbench/plots.py index c73b737..cf7a0e3 100644 --- a/allocbench/plots.py +++ b/allocbench/plots.py @@ -32,7 +32,7 @@ from allocbench.globalvars import SUMMARY_FILE_EXT, LATEX_CUSTOM_PREAMBLE from allocbench.util import print_debug, print_warn # This is useful when evaluating strings in the plot functions. str(np.NaN) == "nan" -nan = np.NaN # pylint: disable=invalid-name +nan = np.NaN # pylint: disable=invalid-name DEFAULT_PLOT_OPTIONS = { 'plot': { @@ -69,20 +69,20 @@ DEFAULT_FIG_OPTIONS = { FIGURES = {} + def _set_all_alloc_colors(allocators): """Populate all not set allocator colors with matplotlib 'C' colors""" explicit_colors = [ v["color"] for v in allocators.values() if v["color"] is not None ] matplotlib_c_colors = ["C" + str(i) for i in range(0, 10)] - avail_colors = [ - c for c in matplotlib_c_colors if c not in explicit_colors - ] + avail_colors = [c for c in matplotlib_c_colors if c not in explicit_colors] for alloc in allocators.values(): if alloc["color"] is None: alloc["color"] = avail_colors.pop() + def get_alloc_color(bench, alloc): """Retrieve color of an allocator""" if isinstance(alloc, str): @@ -96,20 +96,26 @@ def get_alloc_color(bench, alloc): #https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string def _eval_with_stat(bench, evaluation, alloc, perm, stat): """Helper to evaluate a datapoint description string as arithmetic operation""" - def _eval(node): """evaluate a arithmetic ast node""" # supported operators - operators = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, - ast.Div: operator.truediv, ast.Pow: operator.pow, ast.BitXor: operator.xor, - ast.USub: operator.neg} - - if isinstance(node, ast.Num): # <number> + operators = { + ast.Add: operator.add, + ast.Sub: operator.sub, + ast.Mult: operator.mul, + ast.Div: operator.truediv, + ast.Pow: operator.pow, + ast.BitXor: operator.xor, + ast.USub: operator.neg + } + + if isinstance(node, ast.Num): # <number> return node.n - if isinstance(node, ast.BinOp): # <left> <operator> <right> - return operators[type(node.op)](_eval(node.left), _eval(node.right)) - if isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 + if isinstance(node, ast.BinOp): # <left> <operator> <right> + return operators[type(node.op)](_eval(node.left), + _eval(node.right)) + if isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 return operators[type(node.op)](_eval(node.operand)) raise TypeError(node) @@ -128,8 +134,7 @@ def _eval_with_stat(bench, evaluation, alloc, perm, stat): return _eval(node.body) except TypeError: print_debug(traceback.format_exc()) - print_warn( - f"{expr} could not be evaluated as arithmetic operation") + print_warn(f"{expr} could not be evaluated as arithmetic operation") return nan @@ -151,6 +156,7 @@ def get_y_data(bench, expression, allocator, perms, stat="mean", scale=None): return y_data + def _create_plot_options(plot_type, **kwargs): """ Create a plot options dictionary. @@ -177,6 +183,7 @@ def _create_plot_options(plot_type, **kwargs): return options + def _create_figure_options(plot_type, fig_label, **kwargs): """ Create a figure options dictionary @@ -206,6 +213,7 @@ def _create_figure_options(plot_type, fig_label, **kwargs): return options + def _plot(bench, allocators, y_expression, @@ -276,7 +284,8 @@ def _plot(bench, plt.legend(loc=fig_options['legend_pos']) if not fig_options['autoticks']: - plt.xticks(_x_data - (len(allocators) / 2 * plot_options['width']), x_data) + plt.xticks(_x_data - (len(allocators) / 2 * plot_options['width']), + x_data) plt.xlabel(fig_options['xlabel']) plt.ylabel(fig_options['ylabel']) @@ -291,6 +300,7 @@ def _plot(bench, return fig + def plot(bench, y_expression, plot_type='errorbar', @@ -361,14 +371,17 @@ def plot(bench, for loose_arg in x_args: x_data = args[loose_arg] - fixed_args = [[(k, v) for v in args[k]] for k in args if k != loose_arg] + fixed_args = [[(k, v) for v in args[k]] for k in args + if k != loose_arg] for fixed_part_tuple in itertools.product(*fixed_args): - fixed_part = {k:v for k, v in fixed_part_tuple} + fixed_part = {k: v for k, v in fixed_part_tuple} - fixed_part_str = ".".join([f'{k}={v}' for k, v in fixed_part.items()]) + fixed_part_str = ".".join( + [f'{k}={v}' for k, v in fixed_part.items()]) fig_label = f'{bench.name}.{fixed_part_str}.{file_postfix}' - cur_plot_options = _create_plot_options(plot_type, **plot_options or {}) + cur_plot_options = _create_plot_options(plot_type, **plot_options + or {}) cur_fig_options = {} @@ -378,7 +391,8 @@ def plot(bench, if isinstance(value, str): cur_fig_options[option] = value.format(**substitutions) - cur_fig_options = _create_figure_options(plot_type, fig_label, **cur_fig_options) + cur_fig_options = _create_figure_options(plot_type, fig_label, + **cur_fig_options) # plot specific defaults cur_fig_options.setdefault("ylabel", y_expression) @@ -397,13 +411,19 @@ def plot(bench, sumdir=sumdir, file_ext=file_ext) + def print_common_facts(comment_symbol="", file=None): print(comment_symbol, "Common facts:", file=file) for fact, value in facter.FACTS.items(): print(f"{comment_symbol} {fact}: {value}", file=file) print(file=file) -def print_facts(bench, comment_symbol="", print_common=True, print_allocators=False, file=None): + +def print_facts(bench, + comment_symbol="", + print_common=True, + print_allocators=False, + file=None): """Write collected facts about used system and benchmark to file""" print(comment_symbol, bench.name, file=file) print(file=file) @@ -416,7 +436,9 @@ def print_facts(bench, comment_symbol="", print_common=True, print_allocators=Fa print(comment_symbol, f"{fact}: {value}", file=file) if print_allocators: - print(comment_symbol, f'allocators: {" ".join(bench.results["allocators"])}', file=file) + print(comment_symbol, + f'allocators: {" ".join(bench.results["allocators"])}', + file=file) print(file=file) @@ -755,7 +777,7 @@ def pgfplot(bench, for alloc_name, alloc_dict in allocators.items(): if colors: # define color - rgb = matplotlib.colors.to_rgb(get_alloc_color(bench, alloc_dict)) # pylint: disable=unused-variable + rgb = matplotlib.colors.to_rgb(get_alloc_color(bench, alloc_dict)) # pylint: disable=unused-variable color_definitions += (f"\\providecolor{{{alloc_name}-color}}" "{{rgb}}{{{rgb[0]},{rgb[1]},{rgb[2]}}}\n") style_definitions += (f"\\pgfplotsset{{{alloc_name}/" @@ -777,7 +799,12 @@ def pgfplot(bench, for perm in perms: xval = _eval_with_stat(bench, xexpr, alloc_name, perm, "mean") - yval = _get_y_data(bench, yexpr, alloc_name, perm, "mean", scale=scale) + yval = _get_y_data(bench, + yexpr, + alloc_name, + perm, + "mean", + scale=scale) error = "" if error_bars: error = f" {_eval_with_stat(bench, yexpr, alloc_name, perm, 'std')}" diff --git a/allocbench/util.py b/allocbench/util.py index 681211f..ff18137 100644 --- a/allocbench/util.py +++ b/allocbench/util.py @@ -30,7 +30,7 @@ def run_cmd(cmd, shell=False, check=True, cwd=None, - input=None): # pylint: disable=redefined-builtin + input=None): # pylint: disable=redefined-builtin """subprocess.run wrapper which cares about the set verbosity""" if capture: stdout = subprocess.PIPE @@ -16,7 +16,6 @@ # # You should have received a copy of the GNU General Public License # along with allocbench. If not, see <http://www.gnu.org/licenses/>. - """Merge two compatible results of an allocbench run""" import argparse @@ -28,6 +27,7 @@ import sys import allocbench.facter as facter from allocbench.util import print_license_and_exit + def load_file(filename): if filename.endswith("json"): with open(filename, "r") as json_file: @@ -42,13 +42,27 @@ def main(): print_license_and_exit() parser = argparse.ArgumentParser(description="Merge to allocbench results") - parser.add_argument("src", help="results which should be merged into dest", type=str) - parser.add_argument("dest", help="results in which src should be merged", type=str) - parser.add_argument("--license", help="print license info and exit", action='store_true') - parser.add_argument("--version", help="print version info and exit", action='version', + parser.add_argument("src", + help="results which should be merged into dest", + type=str) + parser.add_argument("dest", + help="results in which src should be merged", + type=str) + parser.add_argument("--license", + help="print license info and exit", + action='store_true') + parser.add_argument("--version", + help="print version info and exit", + action='version', version=f"allocbench {facter.allocbench_version()}") - parser.add_argument("-b", "--benchmarks", help="benchmarks to summarize", nargs='+') - parser.add_argument("-x", "--exclude-benchmarks", help="benchmarks to exclude", nargs='+') + parser.add_argument("-b", + "--benchmarks", + help="benchmarks to summarize", + nargs='+') + parser.add_argument("-x", + "--exclude-benchmarks", + help="benchmarks to exclude", + nargs='+') args = parser.parse_args() @@ -66,7 +80,9 @@ def main(): dest_save = os.path.join(args.dest, os.path.basename(src_save)) if not os.path.isfile(dest_save): - print(f"Can't merge {src_save} because {os.path.basename(src_save)} not in {args.dest}") + print( + f"Can't merge {src_save} because {os.path.basename(src_save)} not in {args.dest}" + ) continue src_results = load_file(src_save) @@ -79,11 +95,13 @@ def main(): continue print("merging", alloc, "from", src_save, "into", dest_save) - dest_results["allocators"][alloc] = src_results["allocators"][alloc] + dest_results["allocators"][alloc] = src_results["allocators"][ + alloc] dest_results[alloc] = src_results[alloc] dest_results["stats"][alloc] = src_results["stats"][alloc] - with open(os.path.splitext(dest_save)[0] + ".json", "w") as result_file: + with open(os.path.splitext(dest_save)[0] + ".json", + "w") as result_file: json.dump(dest_results, result_file) diff --git a/scripts/histogram.py b/scripts/histogram.py index 2bf6779..f1f8464 100755 --- a/scripts/histogram.py +++ b/scripts/histogram.py @@ -16,7 +16,6 @@ # # You should have received a copy of the GNU General Public License # along with allocbench. If not, see <http://www.gnu.org/licenses/>. - """Plot an interactive histogram from malt or chattymalloc output file""" import argparse @@ -28,17 +27,29 @@ import sys import matplotlib.pyplot as plt -currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +currentdir = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) parentdir = os.path.dirname(currentdir) sys.path.insert(0, parentdir) def main(): - parser = argparse.ArgumentParser(description="Plot histograms using a malt or chattymalloc output file") - parser.add_argument("input_file", help="path to malt or chattymalloc output file", type=str) - parser.add_argument("-e", "--export", help="export to csv", action="store_true") - parser.add_argument("-n", "--no-ascii", help="don't output a ascii histogram", action="store_true") - parser.add_argument("-i", "--interactive", help="open interactive matplotlib histogram plots", + parser = argparse.ArgumentParser( + description="Plot histograms using a malt or chattymalloc output file") + parser.add_argument("input_file", + help="path to malt or chattymalloc output file", + type=str) + parser.add_argument("-e", + "--export", + help="export to csv", + action="store_true") + parser.add_argument("-n", + "--no-ascii", + help="don't output a ascii histogram", + action="store_true") + parser.add_argument("-i", + "--interactive", + help="open interactive matplotlib histogram plots", action="store_true") args = parser.parse_args() @@ -87,7 +98,6 @@ def main(): else: sizes_bigger_32K.append(size * amount) - plt.figure(0) plt.hist(sizes_smaller_4K, 200) plt.title("Sizes smaller than 4K") @@ -105,5 +115,6 @@ def main(): plt.title("All sizes") plt.show() + if __name__ == "__main__": main() diff --git a/scripts/paper_plots.py b/scripts/paper_plots.py index 49ec15d..f79cf3a 100755 --- a/scripts/paper_plots.py +++ b/scripts/paper_plots.py @@ -24,7 +24,8 @@ import inspect import os import sys -currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +currentdir = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) parentdir = os.path.dirname(currentdir) sys.path.insert(0, parentdir) @@ -36,15 +37,24 @@ from allocbench.util import print_status, print_warn, print_error from allocbench.util import print_license_and_exit ALLOCATOR_NAMES = [a.name for a in paper_allocators] -SURVEY_ALLOCATORS = [a.name for a in paper_allocators if not '-' in a.name or a.name not in ["speedymalloc", "bumpptr"]] +SURVEY_ALLOCATORS = [ + a.name for a in paper_allocators + if not '-' in a.name or a.name not in ["speedymalloc", "bumpptr"] +] TCMALLOCS = [a.name for a in paper_allocators if a.name.startswith("TCMalloc")] -ALIGNED_ALLOCATORS = [a.name for a in paper_allocators if a.name.endswith("-Aligned")] +ALIGNED_ALLOCATORS = [ + a.name for a in paper_allocators if a.name.endswith("-Aligned") +] def falsesharing_plots(falsesharing): args = falsesharing.results["args"] - falsesharing.results["allocators"] = {k: v for k, v in falsesharing.results["allocators"].items() if k in ALLOCATOR_NAMES} + falsesharing.results["allocators"] = { + k: v + for k, v in falsesharing.results["allocators"].items() + if k in ALLOCATOR_NAMES + } plt.pgfplot_legend(falsesharing, columns=5) @@ -53,12 +63,17 @@ def falsesharing_plots(falsesharing): for allocator in falsesharing.results["allocators"]: sequential_perm = falsesharing.Perm(bench=bench, threads=1) - for perm in falsesharing.iterate_args_fixed({"bench": bench}, args=args): - for i, measure in enumerate(falsesharing.results[allocator][perm]): + for perm in falsesharing.iterate_args_fixed({"bench": bench}, + args=args): + for i, measure in enumerate( + falsesharing.results[allocator][perm]): sequential_time = float(falsesharing.results[allocator] - [sequential_perm][i]["time"]) - measure["speedup"] = sequential_time / float(measure["time"]) - measure["l1chache_misses"] = float(measure["L1-dcache-load-misses"]) / float(measure["L1-dcache-loads"]) * 100 + [sequential_perm][i]["time"]) + measure["speedup"] = sequential_time / float( + measure["time"]) + measure["l1chache_misses"] = float( + measure["L1-dcache-load-misses"]) / float( + measure["L1-dcache-loads"]) * 100 # delete and recalculate stats del falsesharing.results["stats"] @@ -67,7 +82,8 @@ def falsesharing_plots(falsesharing): # pgfplots for bench in args["bench"]: plt.pgfplot(falsesharing, - falsesharing.iterate_args_fixed({"bench": bench}, args=args), + falsesharing.iterate_args_fixed({"bench": bench}, + args=args), "int(perm.threads)", "{speedup}", xlabel="Threads", @@ -75,9 +91,14 @@ def falsesharing_plots(falsesharing): title=f"{bench}: Speedup", postfix=f"{bench}.speedup") + def blowup_plots(blowup): args = blowup.results["args"] - blowup.results["allocators"] = {k: v for k, v in blowup.results["allocators"].items() if k in ALLOCATOR_NAMES} + blowup.results["allocators"] = { + k: v + for k, v in blowup.results["allocators"].items() + if k in ALLOCATOR_NAMES + } # hack ideal rss in data set blowup.results["allocators"]["Ideal-RSS"] = {"color": "xkcd:gold"} @@ -86,11 +107,11 @@ def blowup_plots(blowup): blowup.results["stats"]["Ideal-RSS"][perm] = { "mean": { "VmHWM": 1024 * 100 - }, + }, "std": { "VmHWM": 0 - } } + } plt.pgfplot(blowup, blowup.iterate_args(args), @@ -103,9 +124,13 @@ def blowup_plots(blowup): axis_attr="\txtick=data,\n\tsymbolic x coords={blowup}", bar=True) + def loop_plots(loop): args = loop.results["args"] - loop.results["allocators"] = {k: v for k, v in loop.results["allocators"].items() if k in ALLOCATOR_NAMES} + loop.results["allocators"] = { + k: v + for k, v in loop.results["allocators"].items() if k in ALLOCATOR_NAMES + } plt.pgfplot(loop, loop.iterate_args_fixed({"threads": 40}, args), @@ -116,9 +141,10 @@ def loop_plots(loop): title="Loop: 40 threads", postfix="threads.40") + def mysqld_plots(mysql): args = mysql.results["args"] -# mysql.results["allocators"] = {k: v for k, v in mysql.results["allocators"].items() if k in SURVEY_ALLOCATORS} + # mysql.results["allocators"] = {k: v for k, v in mysql.results["allocators"].items() if k in SURVEY_ALLOCATORS} plt.pgfplot(mysql, mysql.iterate_args(args), @@ -142,9 +168,14 @@ def mysqld_plots(mysql): plt.pgfplot_legend(mysql, columns=5) + def keydb_plots(keydb): args = keydb.results["args"] - keydb.results["allocators"] = {k: v for k, v in keydb.results["allocators"].items() if k in SURVEY_ALLOCATORS} + keydb.results["allocators"] = { + k: v + for k, v in keydb.results["allocators"].items() + if k in SURVEY_ALLOCATORS + } for fixed_arg in args: loose_arg = [a for a in args if a != fixed_arg][0] @@ -159,20 +190,26 @@ def keydb_plots(keydb): postfix=f"{fixed_arg}.{arg_value}", bar=True) + def summarize(benchmarks=None, exclude_benchmarks=None): """summarize the benchmarks in the resdir""" cwd = os.getcwd() - for benchmark, func in {"blowup": blowup_plots, "falsesharing": falsesharing_plots, - "mysql": mysqld_plots, "keydb": keydb_plots, - "loop": loop_plots}.items(): + for benchmark, func in { + "blowup": blowup_plots, + "falsesharing": falsesharing_plots, + "mysql": mysqld_plots, + "keydb": keydb_plots, + "loop": loop_plots + }.items(): if benchmarks and not benchmark in benchmarks: continue if exclude_benchmarks and benchmark in exclude_benchmarks: continue - bench_module = importlib.import_module(f"allocbench.benchmarks.{benchmark}") + bench_module = importlib.import_module( + f"allocbench.benchmarks.{benchmark}") if not hasattr(bench_module, benchmark): print_error(f"{benchmark} has no member {benchmark}") @@ -188,7 +225,8 @@ def summarize(benchmarks=None, exclude_benchmarks=None): print_status(f"Summarizing {bench.name} ...") - res_dir = os.path.join(allocbench.globalvars.resdir, bench.name, "paper") + res_dir = os.path.join(allocbench.globalvars.resdir, bench.name, + "paper") if not os.path.isdir(res_dir): os.makedirs(res_dir) os.chdir(res_dir) @@ -216,9 +254,10 @@ def main(): "--exclude-benchmarks", help="benchmarks to exclude", nargs='+') - parser.add_argument("--latex-preamble", - help="latex code to include in the preamble of generated standalones", - type=str) + parser.add_argument( + "--latex-preamble", + help="latex code to include in the preamble of generated standalones", + type=str) args = parser.parse_args() diff --git a/scripts/print_facts.py b/scripts/print_facts.py index 389028e..ec9404c 100755 --- a/scripts/print_facts.py +++ b/scripts/print_facts.py @@ -16,7 +16,6 @@ # # You should have received a copy of the GNU General Public License # along with allocbench. If not, see <http://www.gnu.org/licenses/>. - """Print facts about an allocbench result directory""" import argparse @@ -25,7 +24,8 @@ import inspect import os import sys -CURRENTDIR = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +CURRENTDIR = os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe()))) PARENTDIR = os.path.dirname(CURRENTDIR) sys.path.insert(0, PARENTDIR) @@ -36,7 +36,8 @@ from allocbench.util import print_error def main(): - parser = argparse.ArgumentParser(description="Print facts about an allocbench result directory") + parser = argparse.ArgumentParser( + description="Print facts about an allocbench result directory") parser.add_argument("results", help="path to allocbench results", type=str) args = parser.parse_args() @@ -49,7 +50,8 @@ def main(): os.chdir(args.results) for benchmark in BENCHMARKS: - bench_module = importlib.import_module(f"allocbench.benchmarks.{benchmark}") + bench_module = importlib.import_module( + f"allocbench.benchmarks.{benchmark}") if not hasattr(bench_module, benchmark): print_error(f"{benchmark} has no member {benchmark}") |
