Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ uspace/Makefile	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -50,4 +50,5 @@
 	app/getterm \
 	app/gunzip \
+	app/hbench \
 	app/init \
 	app/inet \
@@ -67,5 +68,4 @@
 	app/nterm \
 	app/pci \
-	app/perf \
 	app/redir \
 	app/sbi \
Index: uspace/app/hbench/Makefile
===================================================================
--- uspace/app/hbench/Makefile	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/Makefile	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2018 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+
+LIBS = math
+
+BINARY = hbench
+
+SOURCES = \
+	benchlist.c \
+	csv.c \
+	main.c \
+	params.c \
+	fs/dirread.c \
+	fs/fileread.c \
+	ipc/ns_ping.c \
+	ipc/ping_pong.c \
+	malloc/malloc1.c \
+	malloc/malloc2.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/hbench/benchlist.c
===================================================================
--- uspace/app/hbench/benchlist.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/benchlist.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * Copyright (c) 2018 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdlib.h>
+#include "benchlist.h"
+
+benchmark_t *benchmarks[] = {
+	&bench_dir_read,
+	&bench_file_read,
+	&bench_malloc1,
+	&bench_malloc2,
+	&bench_ns_ping,
+	&bench_ping_pong
+};
+
+size_t benchmark_count = sizeof(benchmarks) / sizeof(benchmarks[0]);
+
+/** @}
+ */
Index: uspace/app/hbench/benchlist.h
===================================================================
--- uspace/app/hbench/benchlist.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/benchlist.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/** @file
+ */
+
+#ifndef BENCHLIST_H_
+#define BENCHLIST_H_
+
+#include "hbench.h"
+
+extern benchmark_t bench_dir_read;
+extern benchmark_t bench_file_read;
+extern benchmark_t bench_malloc1;
+extern benchmark_t bench_malloc2;
+extern benchmark_t bench_ns_ping;
+extern benchmark_t bench_ping_pong;
+
+extern benchmark_t *benchmarks[];
+extern size_t benchmark_count;
+
+#endif
+
+/** @}
+ */
Index: uspace/app/hbench/csv.c
===================================================================
--- uspace/app/hbench/csv.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/csv.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdlib.h>
+#include "csv.h"
+
+static FILE *csv_output = NULL;
+
+/** Open CSV benchmark report.
+ *
+ * @param filename Filename where to store the CSV.
+ * @return Whether it was possible to open the file.
+ */
+errno_t csv_report_open(const char *filename)
+{
+	csv_output = fopen(filename, "w");
+	if (csv_output == NULL) {
+		return errno;
+	}
+
+	fprintf(csv_output, "benchmark,run,size,duration_nanos\n");
+
+	return EOK;
+}
+
+/** Add one entry to the report.
+ *
+ * When csv_report_open() was not called or failed, the function does
+ * nothing.
+ *
+ * @param stopwatch Performance data of the entry.
+ * @param run_index Run index, use negative values for warm-up.
+ * @param bench Benchmark information.
+ * @param workload_size Workload size.
+ */
+void csv_report_add_entry(stopwatch_t *stopwatch, int run_index,
+    benchmark_t *bench, uint64_t workload_size)
+{
+	if (csv_output == NULL) {
+		return;
+	}
+
+	fprintf(csv_output, "%s,%d,%" PRIu64 ",%lld\n",
+	    bench->name, run_index, workload_size,
+	    (long long) stopwatch_get_nanos(stopwatch));
+}
+
+/** Close CSV report.
+ *
+ * When csv_report_open() was not called or failed, the function does
+ * nothing.
+ */
+void csv_report_close(void)
+{
+	if (csv_output != NULL) {
+		fclose(csv_output);
+	}
+}
+
+/** @}
+ */
Index: uspace/app/hbench/csv.h
===================================================================
--- uspace/app/hbench/csv.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/csv.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CSV_H_
+#define CSV_H_
+
+#include <errno.h>
+#include <stdio.h>
+#include <perf.h>
+#include "hbench.h"
+
+extern errno_t csv_report_open(const char *);
+extern void csv_report_add_entry(stopwatch_t *, int, benchmark_t *, uint64_t);
+extern void csv_report_close(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/hbench/doc/doxygroups.h
===================================================================
--- uspace/app/hbench/doc/doxygroups.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/doc/doxygroups.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,42 @@
+/** @addtogroup hbench hbench
+ * @brief HelenOS user space benchmarks
+ * @ingroup apps
+ *
+ * @details
+ *
+ * To add a new benchmark, you need to implement the actual benchmarking
+ * code and register it.
+ *
+ * Registration is done by adding
+ * <code>extern benchmark_t bench_YOUR_NAME</code> reference to benchlist.h
+ * and by adding it to the array in benchlist.c.
+ *
+ * The actual benchmark should reside in a separate file (see malloc/malloc1.c
+ * for example) and has to (at least) declare one function (the actual
+ * benchmark) and fill-in the benchmark_t structure.
+ *
+ * Fill-in the name of the benchmark, its description and a reference to the
+ * benchmark function to the benchmark_t.
+ *
+ * The benchmarking function has to accept for arguments:
+ *  @li stopwatch_t: store the measured data there
+ *  @li uint64_t: size of the workload - typically number of inner loops in
+ *      your benchmark (used to self-calibrate benchmark size)
+ *  @li char * and size_t giving you access to buffer for storing error message
+ *  if the benchmark fails (return false from the function itself then)
+ *
+ * Typically, the structure of the function is following:
+ * @code{c}
+ * static bool runner(stopwatch_t *stopwatch, uint64_t size,
+ *     char *error, size_t error_size)
+ * {
+ * 	stopwatch_start(stopwatch);
+ * 	for (uint64_t i = 0; i < size; i++) {
+ * 		// measured action
+ * 	}
+ * 	stopwatch_stop(stopwatch);
+ *
+ * 	return true;
+ * }
+ * @endcode
+ */
Index: uspace/app/hbench/fs/dirread.c
===================================================================
--- uspace/app/hbench/fs/dirread.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/fs/dirread.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+
+#include <dirent.h>
+#include <str_error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+#include "../params.h"
+
+/*
+ * Note that while this benchmark tries to measure speed of direct
+ * read, it rather measures speed of FS cache as it is highly probable
+ * that the corresponding blocks would be cached after first run.
+ */
+static bool runner(stopwatch_t *stopwatch, uint64_t size,
+    char *error, size_t error_size)
+{
+	const char *path = bench_param_get("dirname", "/");
+
+	stopwatch_start(stopwatch);
+	for (uint64_t i = 0; i < size; i++) {
+		DIR *dir = opendir(path);
+		if (dir == NULL) {
+			snprintf(error, error_size, "failed to open %s for reading: %s",
+			    path, str_error(errno));
+			return false;
+		}
+
+		struct dirent *dp;
+		while ((dp = readdir(dir))) {
+			/* Do nothing */
+		}
+
+		closedir(dir);
+	}
+	stopwatch_stop(stopwatch);
+
+	return true;
+}
+
+benchmark_t bench_dir_read = {
+	.name = "dir_read",
+	.desc = "Read contents of a directory (use 'dirname' param to alter the default).",
+	.entry = &runner,
+	.setup = NULL,
+	.teardown = NULL
+};
+
+/**
+ * @}
+ */
Index: uspace/app/hbench/fs/fileread.c
===================================================================
--- uspace/app/hbench/fs/fileread.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/fs/fileread.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+
+#include <str_error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+#include "../params.h"
+
+#define BUFFER_SIZE 4096
+
+/*
+ * Note that while this benchmark tries to measure speed of file reading,
+ * it rather measures speed of FS cache as it is highly probable that the
+ * corresponding blocks would be cached after first run.
+ */
+static bool runner(stopwatch_t *stopwatch, uint64_t size,
+    char *error, size_t error_size)
+{
+	const char *path = bench_param_get("filename", "/data/web/helenos.png");
+
+	char *buf = malloc(BUFFER_SIZE);
+	if (buf == NULL) {
+		snprintf(error, error_size, "failed to allocate %dB buffer", BUFFER_SIZE);
+		return false;
+	}
+
+	bool ret = true;
+
+	FILE *file = fopen(path, "r");
+	if (file == NULL) {
+		snprintf(error, error_size, "failed to open %s for reading: %s",
+		    path, str_error(errno));
+		ret = false;
+		goto leave_free_buf;
+	}
+
+	stopwatch_start(stopwatch);
+	for (uint64_t i = 0; i < size; i++) {
+		int rc = fseek(file, 0, SEEK_SET);
+		if (rc != 0) {
+			snprintf(error, error_size, "failed to rewind %s: %s",
+			    path, str_error(errno));
+			ret = false;
+			goto leave_close;
+		}
+		while (!feof(file)) {
+			fread(buf, 1, BUFFER_SIZE, file);
+			if (ferror(file)) {
+				snprintf(error, error_size, "failed to read from %s: %s",
+				    path, str_error(errno));
+				ret = false;
+				goto leave_close;
+			}
+		}
+	}
+	stopwatch_stop(stopwatch);
+
+leave_close:
+	fclose(file);
+
+leave_free_buf:
+	free(buf);
+
+	return ret;
+}
+
+benchmark_t bench_file_read = {
+	.name = "file_read",
+	.desc = "Sequentially read contents of a file (use 'filename' param to alter the default).",
+	.entry = &runner,
+	.setup = NULL,
+	.teardown = NULL
+};
+
+/**
+ * @}
+ */
Index: uspace/app/hbench/hbench.h
===================================================================
--- uspace/app/hbench/hbench.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/hbench.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/** @file
+ */
+
+#ifndef HBENCH_H_
+#define HBENCH_H_
+
+#include <stdbool.h>
+#include <perf.h>
+
+typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t,
+    char *, size_t);
+typedef bool (*benchmark_helper_t)(char *, size_t);
+
+typedef struct {
+	const char *name;
+	const char *desc;
+	benchmark_entry_t entry;
+	benchmark_helper_t setup;
+	benchmark_helper_t teardown;
+} benchmark_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/app/hbench/ipc/ns_ping.c
===================================================================
--- uspace/app/hbench/ipc/ns_ping.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/ipc/ns_ping.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <str_error.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+
+static bool runner(stopwatch_t *stopwatch, uint64_t niter,
+    char *error, size_t error_size)
+{
+	stopwatch_start(stopwatch);
+
+	for (uint64_t count = 0; count < niter; count++) {
+		errno_t rc = ns_ping();
+
+		if (rc != EOK) {
+			snprintf(error, error_size,
+			    "failed sending ping message: %s (%d)",
+			    str_error(rc), rc);
+			return false;
+		}
+	}
+
+	stopwatch_stop(stopwatch);
+
+	return true;
+}
+
+benchmark_t bench_ns_ping = {
+	.name = "ns_ping",
+	.desc = "Name service IPC ping-pong benchmark",
+	.entry = &runner,
+	.setup = NULL,
+	.teardown = NULL
+};
Index: uspace/app/hbench/ipc/ping_pong.c
===================================================================
--- uspace/app/hbench/ipc/ping_pong.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/ipc/ping_pong.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <ipc_test.h>
+#include <async.h>
+#include <errno.h>
+#include <str_error.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+
+static ipc_test_t *test = NULL;
+
+static bool setup(char *error, size_t error_size)
+{
+	errno_t rc = ipc_test_create(&test);
+	if (rc != EOK) {
+		snprintf(error, error_size,
+		    "failed contacting IPC test server (have you run /srv/test/ipc-test?): %s (%d)",
+		    str_error(rc), rc);
+		return false;
+	}
+
+	return true;
+}
+
+static bool teardown(char *error, size_t error_size)
+{
+	ipc_test_destroy(test);
+	return true;
+}
+
+static bool runner(stopwatch_t *stopwatch, uint64_t niter,
+    char *error, size_t error_size)
+{
+	stopwatch_start(stopwatch);
+
+	for (uint64_t count = 0; count < niter; count++) {
+		errno_t rc = ipc_test_ping(test);
+
+		if (rc != EOK) {
+			snprintf(error, error_size,
+			    "failed sending ping message: %s (%d)",
+			    str_error(rc), rc);
+			return false;
+		}
+	}
+
+	stopwatch_stop(stopwatch);
+
+	return true;
+}
+
+benchmark_t bench_ping_pong = {
+	.name = "ping_pong",
+	.desc = "IPC ping-pong benchmark",
+	.entry = &runner,
+	.setup = &setup,
+	.teardown = &teardown
+};
Index: uspace/app/hbench/main.c
===================================================================
--- uspace/app/hbench/main.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/main.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * Copyright (c) 2018 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <getopt.h>
+#include <math.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <str.h>
+#include <time.h>
+#include <errno.h>
+#include <str_error.h>
+#include <perf.h>
+#include <types/casting.h>
+#include "benchlist.h"
+#include "csv.h"
+#include "hbench.h"
+#include "params.h"
+
+#define MIN_DURATION_SECS 10
+#define NUM_SAMPLES 10
+#define MAX_ERROR_STR_LENGTH 1024
+
+static void short_report(stopwatch_t *stopwatch, int run_index,
+    benchmark_t *bench, uint64_t workload_size)
+{
+	csv_report_add_entry(stopwatch, run_index, bench, workload_size);
+
+	usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(stopwatch));
+
+	printf("Completed %" PRIu64 " operations in %llu us",
+	    workload_size, duration_usec);
+	if (duration_usec > 0) {
+		double nanos = stopwatch_get_nanos(stopwatch);
+		double thruput = (double) workload_size / (nanos / 1000000000.0l);
+		printf(", %.0f ops/s.\n", thruput);
+	} else {
+		printf(".\n");
+	}
+}
+
+/*
+ * This is a temporary solution until we have proper sqrt() implementation
+ * in libmath.
+ *
+ * The algorithm uses Babylonian method [1].
+ *
+ * [1] https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
+ */
+static double estimate_square_root(double value, double precision)
+{
+	double estimate = 1.;
+	double prev_estimate = estimate + 10 * precision;
+
+	while (fabs(estimate - prev_estimate) > precision) {
+		prev_estimate = estimate;
+		estimate = (prev_estimate + value / prev_estimate) / 2.;
+	}
+
+	return estimate;
+}
+
+/*
+ * Compute available statistics from given stopwatches.
+ *
+ * We compute normal mean for average duration of the workload and geometric
+ * mean for average thruput. Note that geometric mean is necessary to compute
+ * average throughput correctly - consider the following example:
+ *  - we run always 60 operations,
+ *  - first run executes in 30 s (i.e. 2 ops/s)
+ *  - and second one in 10 s (6 ops/s).
+ * Then, naively, average throughput would be (2+6)/2 = 4 [ops/s]. However, we
+ * actually executed 60 + 60 ops in 30 + 10 seconds. So the actual average
+ * throughput is 3 ops/s (which is exactly what geometric mean means).
+ *
+ */
+static void compute_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
+    uint64_t workload_size, double precision, double *out_duration_avg,
+    double *out_duration_sigma, double *out_thruput_avg)
+{
+	double inv_thruput_sum = 0.0;
+	double nanos_sum = 0.0;
+	double nanos_sum2 = 0.0;
+
+	for (size_t i = 0; i < stopwatch_count; i++) {
+		double nanos = stopwatch_get_nanos(&stopwatch[i]);
+		double thruput = (double) workload_size / nanos;
+
+		inv_thruput_sum += 1.0 / thruput;
+		nanos_sum += nanos;
+		nanos_sum2 += nanos * nanos;
+	}
+	*out_duration_avg = nanos_sum / stopwatch_count;
+	double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) /
+	    ((double) stopwatch_count - 1);
+	// FIXME: implement sqrt properly
+	*out_duration_sigma = estimate_square_root(sigma2, precision);
+	*out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count);
+}
+
+static void summary_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
+    benchmark_t *bench, uint64_t workload_size)
+{
+	double duration_avg, duration_sigma, thruput_avg;
+	compute_stats(stopwatch, stopwatch_count, workload_size, 0.001,
+	    &duration_avg, &duration_sigma, &thruput_avg);
+
+	printf("Average: %" PRIu64 " ops in %.0f us (sd %.0f us); "
+	    "%.0f ops/s; Samples: %zu\n",
+	    workload_size, duration_avg / 1000.0, duration_sigma / 1000.0,
+	    thruput_avg * 1000000000.0, stopwatch_count);
+}
+
+static bool run_benchmark(benchmark_t *bench)
+{
+	printf("Warm up and determine workload size...\n");
+
+	char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1);
+	if (error_msg == NULL) {
+		printf("Out of memory!\n");
+		return false;
+	}
+	str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "");
+
+	bool ret = true;
+
+	if (bench->setup != NULL) {
+		ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH);
+		if (!ret) {
+			goto leave_error;
+		}
+	}
+
+	/*
+	 * Find workload size that is big enough to last few seconds.
+	 * We also check that uint64_t is big enough.
+	 */
+	uint64_t workload_size = 0;
+	for (size_t bits = 0; bits <= 64; bits++) {
+		if (bits == 64) {
+			str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "Workload too small even for 1 << 63");
+			goto leave_error;
+		}
+		workload_size = ((uint64_t) 1) << bits;
+
+		stopwatch_t stopwatch = STOPWATCH_INITIALIZE_STATIC;
+
+		bool ok = bench->entry(&stopwatch, workload_size,
+		    error_msg, MAX_ERROR_STR_LENGTH);
+		if (!ok) {
+			goto leave_error;
+		}
+		short_report(&stopwatch, -1, bench, workload_size);
+
+		nsec_t duration = stopwatch_get_nanos(&stopwatch);
+		if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
+			break;
+		}
+	}
+
+	printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES);
+
+	stopwatch_t *stopwatch = calloc(NUM_SAMPLES, sizeof(stopwatch_t));
+	if (stopwatch == NULL) {
+		snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
+		goto leave_error;
+	}
+	for (int i = 0; i < NUM_SAMPLES; i++) {
+		stopwatch_init(&stopwatch[i]);
+
+		bool ok = bench->entry(&stopwatch[i], workload_size,
+		    error_msg, MAX_ERROR_STR_LENGTH);
+		if (!ok) {
+			free(stopwatch);
+			goto leave_error;
+		}
+		short_report(&stopwatch[i], i, bench, workload_size);
+	}
+
+	summary_stats(stopwatch, NUM_SAMPLES, bench, workload_size);
+	printf("\nBenchmark completed\n");
+
+	free(stopwatch);
+
+	goto leave;
+
+leave_error:
+	printf("Error: %s\n", error_msg);
+	ret = false;
+
+leave:
+	if (bench->teardown != NULL) {
+		bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH);
+		if (!ok) {
+			printf("Error: %s\n", error_msg);
+			ret = false;
+		}
+	}
+
+	free(error_msg);
+
+	return ret;
+}
+
+static int run_benchmarks(void)
+{
+	unsigned int count_ok = 0;
+	unsigned int count_fail = 0;
+
+	char *failed_names = NULL;
+
+	printf("\n*** Running all benchmarks ***\n\n");
+
+	for (size_t it = 0; it < benchmark_count; it++) {
+		printf("%s (%s)\n", benchmarks[it]->name, benchmarks[it]->desc);
+		if (run_benchmark(benchmarks[it])) {
+			count_ok++;
+			continue;
+		}
+
+		if (!failed_names) {
+			failed_names = str_dup(benchmarks[it]->name);
+		} else {
+			char *f = NULL;
+			asprintf(&f, "%s, %s", failed_names, benchmarks[it]->name);
+			if (!f) {
+				printf("Out of memory.\n");
+				abort();
+			}
+			free(failed_names);
+			failed_names = f;
+		}
+		count_fail++;
+	}
+
+	printf("\nCompleted, %u benchmarks run, %u succeeded.\n",
+	    count_ok + count_fail, count_ok);
+	if (failed_names)
+		printf("Failed benchmarks: %s\n", failed_names);
+
+	return count_fail;
+}
+
+static void list_benchmarks(void)
+{
+	size_t len = 0;
+	for (size_t i = 0; i < benchmark_count; i++) {
+		size_t len_now = str_length(benchmarks[i]->name);
+		if (len_now > len)
+			len = len_now;
+	}
+
+	assert(can_cast_size_t_to_int(len) && "benchmark name length overflow");
+
+	for (size_t i = 0; i < benchmark_count; i++)
+		printf("  %-*s %s\n", (int) len, benchmarks[i]->name, benchmarks[i]->desc);
+
+	printf("  %-*s Run all benchmarks\n", (int) len, "*");
+}
+
+static void print_usage(const char *progname)
+{
+	printf("Usage: %s [options] <benchmark>\n", progname);
+	printf("-h, --help                 "
+	    "Print this help and exit\n");
+	printf("-o, --output filename.csv  "
+	    "Store machine-readable data in filename.csv\n");
+	printf("-p, --param KEY=VALUE      "
+	    "Additional parameters for the benchmark\n");
+	printf("<benchmark> is one of the following:\n");
+	list_benchmarks();
+}
+
+static void handle_param_arg(char *arg)
+{
+	char *value = NULL;
+	char *key = str_tok(arg, "=", &value);
+	bench_param_set(key, value);
+}
+
+int main(int argc, char *argv[])
+{
+	errno_t rc = bench_param_init();
+	if (rc != EOK) {
+		fprintf(stderr, "Failed to initialize internal params structure: %s\n",
+		    str_error(rc));
+		return -5;
+	}
+
+	const char *short_options = "ho:p:";
+	struct option long_options[] = {
+		{ "help", optional_argument, NULL, 'h' },
+		{ "param", required_argument, NULL, 'p' },
+		{ "output", required_argument, NULL, 'o' },
+		{ 0, 0, NULL, 0 }
+	};
+
+	char *csv_output_filename = NULL;
+
+	int opt = 0;
+	while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) > 0) {
+		switch (opt) {
+		case 'h':
+			print_usage(*argv);
+			return 0;
+		case 'o':
+			csv_output_filename = optarg;
+			break;
+		case 'p':
+			handle_param_arg(optarg);
+			break;
+		case -1:
+		default:
+			break;
+		}
+	}
+
+	if (optind + 1 != argc) {
+		print_usage(*argv);
+		fprintf(stderr, "Error: specify one benchmark to run or * for all.\n");
+		return -3;
+	}
+
+	const char *benchmark = argv[optind];
+
+	if (csv_output_filename != NULL) {
+		errno_t rc = csv_report_open(csv_output_filename);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed to open CSV report '%s': %s\n",
+			    csv_output_filename, str_error(rc));
+			return -4;
+		}
+	}
+
+	int exit_code = 0;
+
+	if (str_cmp(benchmark, "*") == 0) {
+		exit_code = run_benchmarks();
+	} else {
+		bool benchmark_exists = false;
+		for (size_t i = 0; i < benchmark_count; i++) {
+			if (str_cmp(benchmark, benchmarks[i]->name) == 0) {
+				benchmark_exists = true;
+				exit_code = run_benchmark(benchmarks[i]) ? 0 : -1;
+				break;
+			}
+		}
+		if (!benchmark_exists) {
+			printf("Unknown benchmark \"%s\"\n", benchmark);
+			exit_code = -2;
+		}
+	}
+
+	csv_report_close();
+	bench_param_cleanup();
+
+	return exit_code;
+}
+
+/** @}
+ */
Index: uspace/app/hbench/malloc/malloc1.c
===================================================================
--- uspace/app/hbench/malloc/malloc1.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/malloc/malloc1.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+
+static bool runner(stopwatch_t *stopwatch, uint64_t size,
+    char *error, size_t error_size)
+{
+	stopwatch_start(stopwatch);
+	for (uint64_t i = 0; i < size; i++) {
+		void *p = malloc(1);
+		if (p == NULL) {
+			snprintf(error, error_size,
+			    "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
+			    i, size);
+			return false;
+		}
+		free(p);
+	}
+	stopwatch_stop(stopwatch);
+
+	return true;
+}
+
+benchmark_t bench_malloc1 = {
+	.name = "malloc1",
+	.desc = "User-space memory allocator benchmark, repeatedly allocate one block",
+	.entry = &runner,
+	.setup = NULL,
+	.teardown = NULL
+};
Index: uspace/app/hbench/malloc/malloc2.c
===================================================================
--- uspace/app/hbench/malloc/malloc2.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/malloc/malloc2.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "../benchlist.h"
+#include "../hbench.h"
+
+static bool runner(stopwatch_t *stopwatch, uint64_t niter,
+    char *error, size_t error_size)
+{
+	stopwatch_start(stopwatch);
+
+	void **p = malloc(niter * sizeof(void *));
+	if (p == NULL) {
+		snprintf(error, error_size,
+		    "failed to allocate backend array (%" PRIu64 "B)",
+		    niter * sizeof(void *));
+		return false;
+	}
+
+	for (uint64_t count = 0; count < niter; count++) {
+		p[count] = malloc(1);
+		if (p[count] == NULL) {
+			snprintf(error, error_size,
+			    "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
+			    count, niter);
+			for (uint64_t j = 0; j < count; j++) {
+				free(p[j]);
+			}
+			free(p);
+			return false;
+		}
+	}
+
+	for (uint64_t count = 0; count < niter; count++)
+		free(p[count]);
+
+	free(p);
+
+	stopwatch_stop(stopwatch);
+
+	return true;
+}
+
+benchmark_t bench_malloc2 = {
+	.name = "malloc2",
+	.desc = "User-space memory allocator benchmark, allocate many small blocks",
+	.entry = &runner,
+	.setup = NULL,
+	.teardown = NULL
+};
Index: uspace/app/hbench/params.c
===================================================================
--- uspace/app/hbench/params.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/params.c	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <adt/hash_table.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <str.h>
+#include "params.h"
+
+typedef struct {
+	ht_link_t link;
+
+	char *key;
+	char *value;
+} param_t;
+
+static size_t param_hash(const ht_link_t *item)
+{
+	param_t *param = hash_table_get_inst(item, param_t, link);
+	return str_size(param->key);
+}
+
+static size_t param_key_hash(void *key)
+{
+	char *key_str = key;
+	return str_size(key_str);
+}
+
+static bool param_key_equal(void *key, const ht_link_t *item)
+{
+	param_t *param = hash_table_get_inst(item, param_t, link);
+	char *key_str = key;
+
+	return str_cmp(param->key, key_str) == 0;
+}
+
+static bool param_equal(const ht_link_t *link_a, const ht_link_t *link_b)
+{
+	param_t *a = hash_table_get_inst(link_a, param_t, link);
+	param_t *b = hash_table_get_inst(link_b, param_t, link);
+
+	return str_cmp(a->key, b->key) == 0;
+}
+
+static void param_remove(ht_link_t *item)
+{
+	param_t *param = hash_table_get_inst(item, param_t, link);
+	free(param->key);
+	free(param->value);
+}
+
+static hash_table_ops_t param_hash_table_ops = {
+	.hash = param_hash,
+	.key_hash = param_key_hash,
+	.key_equal = param_key_equal,
+	.equal = param_equal,
+	.remove_callback = param_remove
+};
+
+/** Table of extra parameters (of param_t). */
+static hash_table_t param_hash_table;
+
+extern errno_t bench_param_init(void)
+{
+	bool ok = hash_table_create(&param_hash_table, 0, 0, &param_hash_table_ops);
+	if (!ok) {
+		return ENOMEM;
+	}
+
+	return EOK;
+}
+
+extern void bench_param_cleanup(void)
+{
+	hash_table_destroy(&param_hash_table);
+}
+
+errno_t bench_param_set(const char *key, const char *value)
+{
+	param_t *param = malloc(sizeof(param_t));
+	if (param == NULL) {
+		return ENOMEM;
+	}
+
+	param->key = str_dup(key);
+	param->value = str_dup(value);
+
+	if ((param->key == NULL) || (param->value == NULL)) {
+		free(param->key);
+		free(param->value);
+		free(param);
+
+		return ENOMEM;
+	}
+
+	hash_table_insert(&param_hash_table, &param->link);
+
+	return EOK;
+}
+
+const char *bench_param_get(const char *key, const char *default_value)
+{
+	ht_link_t *item = hash_table_find(&param_hash_table, (char *) key);
+
+	if (item == NULL) {
+		return default_value;
+	}
+
+	param_t *param = hash_table_get_inst(item, param_t, link);
+	return param->value;
+}
+
+/** @}
+ */
Index: uspace/app/hbench/params.h
===================================================================
--- uspace/app/hbench/params.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
+++ uspace/app/hbench/params.h	(revision fe656783f1136cc632328ef6c088aad3cb650fdd)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup hbench
+ * @{
+ */
+/** @file
+ */
+
+#ifndef PARAMS_H_
+#define PARAMS_H_
+
+extern errno_t bench_param_init(void);
+extern errno_t bench_param_set(const char *, const char *);
+extern const char *bench_param_get(const char *, const char *);
+extern void bench_param_cleanup(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/perf/Makefile
===================================================================
--- uspace/app/perf/Makefile	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,47 +1,0 @@
-#
-# Copyright (c) 2018 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = math
-
-BINARY = perf
-
-SOURCES = \
-	benchlist.c \
-	csv.c \
-	params.c \
-	perf.c \
-	fs/dirread.c \
-	fs/fileread.c \
-	ipc/ns_ping.c \
-	ipc/ping_pong.c \
-	malloc/malloc1.c \
-	malloc/malloc2.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/perf/benchlist.c
===================================================================
--- uspace/app/perf/benchlist.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * Copyright (c) 2018 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/**
- * @file
- */
-
-#include <stdlib.h>
-#include "benchlist.h"
-
-benchmark_t *benchmarks[] = {
-	&bench_dir_read,
-	&bench_file_read,
-	&bench_malloc1,
-	&bench_malloc2,
-	&bench_ns_ping,
-	&bench_ping_pong
-};
-
-size_t benchmark_count = sizeof(benchmarks) / sizeof(benchmarks[0]);
-
-/** @}
- */
Index: uspace/app/perf/benchlist.h
===================================================================
--- uspace/app/perf/benchlist.h	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/** @file
- */
-
-#ifndef BENCHLIST_H_
-#define BENCHLIST_H_
-
-#include "perf.h"
-
-extern benchmark_t bench_dir_read;
-extern benchmark_t bench_file_read;
-extern benchmark_t bench_malloc1;
-extern benchmark_t bench_malloc2;
-extern benchmark_t bench_ns_ping;
-extern benchmark_t bench_ping_pong;
-
-extern benchmark_t *benchmarks[];
-extern size_t benchmark_count;
-
-#endif
-
-/** @}
- */
Index: uspace/app/perf/csv.c
===================================================================
--- uspace/app/perf/csv.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,93 +1,0 @@
-/*
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/**
- * @file
- */
-
-#include <stdlib.h>
-#include "csv.h"
-
-static FILE *csv_output = NULL;
-
-/** Open CSV benchmark report.
- *
- * @param filename Filename where to store the CSV.
- * @return Whether it was possible to open the file.
- */
-errno_t csv_report_open(const char *filename)
-{
-	csv_output = fopen(filename, "w");
-	if (csv_output == NULL) {
-		return errno;
-	}
-
-	fprintf(csv_output, "benchmark,run,size,duration_nanos\n");
-
-	return EOK;
-}
-
-/** Add one entry to the report.
- *
- * When csv_report_open() was not called or failed, the function does
- * nothing.
- *
- * @param stopwatch Performance data of the entry.
- * @param run_index Run index, use negative values for warm-up.
- * @param bench Benchmark information.
- * @param workload_size Workload size.
- */
-void csv_report_add_entry(stopwatch_t *stopwatch, int run_index,
-    benchmark_t *bench, uint64_t workload_size)
-{
-	if (csv_output == NULL) {
-		return;
-	}
-
-	fprintf(csv_output, "%s,%d,%" PRIu64 ",%lld\n",
-	    bench->name, run_index, workload_size,
-	    (long long) stopwatch_get_nanos(stopwatch));
-}
-
-/** Close CSV report.
- *
- * When csv_report_open() was not called or failed, the function does
- * nothing.
- */
-void csv_report_close(void)
-{
-	if (csv_output != NULL) {
-		fclose(csv_output);
-	}
-}
-
-/** @}
- */
Index: uspace/app/perf/csv.h
===================================================================
--- uspace/app/perf/csv.h	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/** @file
- */
-
-#ifndef CSV_H_
-#define CSV_H_
-
-#include <errno.h>
-#include <stdio.h>
-#include <perf.h>
-#include "perf.h"
-
-extern errno_t csv_report_open(const char *);
-extern void csv_report_add_entry(stopwatch_t *, int, benchmark_t *, uint64_t);
-extern void csv_report_close(void);
-
-#endif
-
-/** @}
- */
Index: uspace/app/perf/doc/doxygroups.h
===================================================================
--- uspace/app/perf/doc/doxygroups.h	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/** @addtogroup perf perf
- * @brief User space performance measuring tool
- * @ingroup apps
- *
- * @details
- *
- * To add a new benchmark, you need to implement the actual benchmarking
- * code and register it.
- *
- * Registration is done by adding
- * <code>extern benchmark_t bench_YOUR_NAME</code> reference to benchlist.h
- * and by adding it to the array in benchlist.c.
- *
- * The actual benchmark should reside in a separate file (see malloc/malloc1.c
- * for example) and has to (at least) declare one function (the actual
- * benchmark) and fill-in the benchmark_t structure.
- *
- * Fill-in the name of the benchmark, its description and a reference to the
- * benchmark function to the benchmark_t.
- *
- * The benchmarking function has to accept for arguments:
- *  @li stopwatch_t: store the measured data there
- *  @li uint64_t: size of the workload - typically number of inner loops in
- *      your benchmark (used to self-calibrate benchmark size)
- *  @li char * and size_t giving you access to buffer for storing error message
- *  if the benchmark fails (return false from the function itself then)
- *
- * Typically, the structure of the function is following:
- * @code{c}
- * static bool runner(stopwatch_t *stopwatch, uint64_t size,
- *     char *error, size_t error_size)
- * {
- * 	stopwatch_start(stopwatch);
- * 	for (uint64_t i = 0; i < size; i++) {
- * 		// measured action
- * 	}
- * 	stopwatch_stop(stopwatch);
- *
- * 	return true;
- * }
- * @endcode
- */
Index: uspace/app/perf/fs/dirread.c
===================================================================
--- uspace/app/perf/fs/dirread.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,83 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-
-#include <dirent.h>
-#include <str_error.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "../benchlist.h"
-#include "../perf.h"
-#include "../params.h"
-
-/*
- * Note that while this benchmark tries to measure speed of direct
- * read, it rather measures speed of FS cache as it is highly probable
- * that the corresponding blocks would be cached after first run.
- */
-static bool runner(stopwatch_t *stopwatch, uint64_t size,
-    char *error, size_t error_size)
-{
-	const char *path = bench_param_get("dirname", "/");
-
-	stopwatch_start(stopwatch);
-	for (uint64_t i = 0; i < size; i++) {
-		DIR *dir = opendir(path);
-		if (dir == NULL) {
-			snprintf(error, error_size, "failed to open %s for reading: %s",
-			    path, str_error(errno));
-			return false;
-		}
-
-		struct dirent *dp;
-		while ((dp = readdir(dir))) {
-			/* Do nothing */
-		}
-
-		closedir(dir);
-	}
-	stopwatch_stop(stopwatch);
-
-	return true;
-}
-
-benchmark_t bench_dir_read = {
-	.name = "dir_read",
-	.desc = "Read contents of a directory (use 'dirname' param to alter the default).",
-	.entry = &runner,
-	.setup = NULL,
-	.teardown = NULL
-};
-
-/**
- * @}
- */
Index: uspace/app/perf/fs/fileread.c
===================================================================
--- uspace/app/perf/fs/fileread.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,109 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-
-#include <str_error.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "../benchlist.h"
-#include "../perf.h"
-#include "../params.h"
-
-#define BUFFER_SIZE 4096
-
-/*
- * Note that while this benchmark tries to measure speed of file reading,
- * it rather measures speed of FS cache as it is highly probable that the
- * corresponding blocks would be cached after first run.
- */
-static bool runner(stopwatch_t *stopwatch, uint64_t size,
-    char *error, size_t error_size)
-{
-	const char *path = bench_param_get("filename", "/data/web/helenos.png");
-
-	char *buf = malloc(BUFFER_SIZE);
-	if (buf == NULL) {
-		snprintf(error, error_size, "failed to allocate %dB buffer", BUFFER_SIZE);
-		return false;
-	}
-
-	bool ret = true;
-
-	FILE *file = fopen(path, "r");
-	if (file == NULL) {
-		snprintf(error, error_size, "failed to open %s for reading: %s",
-		    path, str_error(errno));
-		ret = false;
-		goto leave_free_buf;
-	}
-
-	stopwatch_start(stopwatch);
-	for (uint64_t i = 0; i < size; i++) {
-		int rc = fseek(file, 0, SEEK_SET);
-		if (rc != 0) {
-			snprintf(error, error_size, "failed to rewind %s: %s",
-			    path, str_error(errno));
-			ret = false;
-			goto leave_close;
-		}
-		while (!feof(file)) {
-			fread(buf, 1, BUFFER_SIZE, file);
-			if (ferror(file)) {
-				snprintf(error, error_size, "failed to read from %s: %s",
-				    path, str_error(errno));
-				ret = false;
-				goto leave_close;
-			}
-		}
-	}
-	stopwatch_stop(stopwatch);
-
-leave_close:
-	fclose(file);
-
-leave_free_buf:
-	free(buf);
-
-	return ret;
-}
-
-benchmark_t bench_file_read = {
-	.name = "file_read",
-	.desc = "Sequentially read contents of a file (use 'filename' param to alter the default).",
-	.entry = &runner,
-	.setup = NULL,
-	.teardown = NULL
-};
-
-/**
- * @}
- */
Index: uspace/app/perf/ipc/ns_ping.c
===================================================================
--- uspace/app/perf/ipc/ns_ping.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <str_error.h>
-#include "../benchlist.h"
-#include "../perf.h"
-
-static bool runner(stopwatch_t *stopwatch, uint64_t niter,
-    char *error, size_t error_size)
-{
-	stopwatch_start(stopwatch);
-
-	for (uint64_t count = 0; count < niter; count++) {
-		errno_t rc = ns_ping();
-
-		if (rc != EOK) {
-			snprintf(error, error_size,
-			    "failed sending ping message: %s (%d)",
-			    str_error(rc), rc);
-			return false;
-		}
-	}
-
-	stopwatch_stop(stopwatch);
-
-	return true;
-}
-
-benchmark_t bench_ns_ping = {
-	.name = "ns_ping",
-	.desc = "Name service IPC ping-pong benchmark",
-	.entry = &runner,
-	.setup = NULL,
-	.teardown = NULL
-};
Index: uspace/app/perf/ipc/ping_pong.c
===================================================================
--- uspace/app/perf/ipc/ping_pong.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <ipc_test.h>
-#include <async.h>
-#include <errno.h>
-#include <str_error.h>
-#include "../benchlist.h"
-#include "../perf.h"
-
-static ipc_test_t *test = NULL;
-
-static bool setup(char *error, size_t error_size)
-{
-	errno_t rc = ipc_test_create(&test);
-	if (rc != EOK) {
-		snprintf(error, error_size,
-		    "failed contacting IPC test server (have you run /srv/test/ipc-test?): %s (%d)",
-		    str_error(rc), rc);
-		return false;
-	}
-
-	return true;
-}
-
-static bool teardown(char *error, size_t error_size)
-{
-	ipc_test_destroy(test);
-	return true;
-}
-
-static bool runner(stopwatch_t *stopwatch, uint64_t niter,
-    char *error, size_t error_size)
-{
-	stopwatch_start(stopwatch);
-
-	for (uint64_t count = 0; count < niter; count++) {
-		errno_t rc = ipc_test_ping(test);
-
-		if (rc != EOK) {
-			snprintf(error, error_size,
-			    "failed sending ping message: %s (%d)",
-			    str_error(rc), rc);
-			return false;
-		}
-	}
-
-	stopwatch_stop(stopwatch);
-
-	return true;
-}
-
-benchmark_t bench_ping_pong = {
-	.name = "ping_pong",
-	.desc = "IPC ping-pong benchmark",
-	.entry = &runner,
-	.setup = &setup,
-	.teardown = &teardown
-};
Index: uspace/app/perf/malloc/malloc1.c
===================================================================
--- uspace/app/perf/malloc/malloc1.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "../benchlist.h"
-#include "../perf.h"
-
-static bool runner(stopwatch_t *stopwatch, uint64_t size,
-    char *error, size_t error_size)
-{
-	stopwatch_start(stopwatch);
-	for (uint64_t i = 0; i < size; i++) {
-		void *p = malloc(1);
-		if (p == NULL) {
-			snprintf(error, error_size,
-			    "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
-			    i, size);
-			return false;
-		}
-		free(p);
-	}
-	stopwatch_stop(stopwatch);
-
-	return true;
-}
-
-benchmark_t bench_malloc1 = {
-	.name = "malloc1",
-	.desc = "User-space memory allocator benchmark, repeatedly allocate one block",
-	.entry = &runner,
-	.setup = NULL,
-	.teardown = NULL
-};
Index: uspace/app/perf/malloc/malloc2.c
===================================================================
--- uspace/app/perf/malloc/malloc2.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "../benchlist.h"
-#include "../perf.h"
-
-static bool runner(stopwatch_t *stopwatch, uint64_t niter,
-    char *error, size_t error_size)
-{
-	stopwatch_start(stopwatch);
-
-	void **p = malloc(niter * sizeof(void *));
-	if (p == NULL) {
-		snprintf(error, error_size,
-		    "failed to allocate backend array (%" PRIu64 "B)",
-		    niter * sizeof(void *));
-		return false;
-	}
-
-	for (uint64_t count = 0; count < niter; count++) {
-		p[count] = malloc(1);
-		if (p[count] == NULL) {
-			snprintf(error, error_size,
-			    "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",
-			    count, niter);
-			for (uint64_t j = 0; j < count; j++) {
-				free(p[j]);
-			}
-			free(p);
-			return false;
-		}
-	}
-
-	for (uint64_t count = 0; count < niter; count++)
-		free(p[count]);
-
-	free(p);
-
-	stopwatch_stop(stopwatch);
-
-	return true;
-}
-
-benchmark_t bench_malloc2 = {
-	.name = "malloc2",
-	.desc = "User-space memory allocator benchmark, allocate many small blocks",
-	.entry = &runner,
-	.setup = NULL,
-	.teardown = NULL
-};
Index: uspace/app/perf/params.c
===================================================================
--- uspace/app/perf/params.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,146 +1,0 @@
-/*
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/**
- * @file
- */
-
-#include <adt/hash_table.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <str.h>
-#include "params.h"
-
-typedef struct {
-	ht_link_t link;
-
-	char *key;
-	char *value;
-} param_t;
-
-static size_t param_hash(const ht_link_t *item)
-{
-	param_t *param = hash_table_get_inst(item, param_t, link);
-	return str_size(param->key);
-}
-
-static size_t param_key_hash(void *key)
-{
-	char *key_str = key;
-	return str_size(key_str);
-}
-
-static bool param_key_equal(void *key, const ht_link_t *item)
-{
-	param_t *param = hash_table_get_inst(item, param_t, link);
-	char *key_str = key;
-
-	return str_cmp(param->key, key_str) == 0;
-}
-
-static bool param_equal(const ht_link_t *link_a, const ht_link_t *link_b)
-{
-	param_t *a = hash_table_get_inst(link_a, param_t, link);
-	param_t *b = hash_table_get_inst(link_b, param_t, link);
-
-	return str_cmp(a->key, b->key) == 0;
-}
-
-static void param_remove(ht_link_t *item)
-{
-	param_t *param = hash_table_get_inst(item, param_t, link);
-	free(param->key);
-	free(param->value);
-}
-
-static hash_table_ops_t param_hash_table_ops = {
-	.hash = param_hash,
-	.key_hash = param_key_hash,
-	.key_equal = param_key_equal,
-	.equal = param_equal,
-	.remove_callback = param_remove
-};
-
-/** Table of extra parameters (of param_t). */
-static hash_table_t param_hash_table;
-
-extern errno_t bench_param_init(void)
-{
-	bool ok = hash_table_create(&param_hash_table, 0, 0, &param_hash_table_ops);
-	if (!ok) {
-		return ENOMEM;
-	}
-
-	return EOK;
-}
-
-extern void bench_param_cleanup(void)
-{
-	hash_table_destroy(&param_hash_table);
-}
-
-errno_t bench_param_set(const char *key, const char *value)
-{
-	param_t *param = malloc(sizeof(param_t));
-	if (param == NULL) {
-		return ENOMEM;
-	}
-
-	param->key = str_dup(key);
-	param->value = str_dup(value);
-
-	if ((param->key == NULL) || (param->value == NULL)) {
-		free(param->key);
-		free(param->value);
-		free(param);
-
-		return ENOMEM;
-	}
-
-	hash_table_insert(&param_hash_table, &param->link);
-
-	return EOK;
-}
-
-const char *bench_param_get(const char *key, const char *default_value)
-{
-	ht_link_t *item = hash_table_find(&param_hash_table, (char *) key);
-
-	if (item == NULL) {
-		return default_value;
-	}
-
-	param_t *param = hash_table_get_inst(item, param_t, link);
-	return param->value;
-}
-
-/** @}
- */
Index: uspace/app/perf/params.h
===================================================================
--- uspace/app/perf/params.h	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2019 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/** @file
- */
-
-#ifndef PARAMS_H_
-#define PARAMS_H_
-
-extern errno_t bench_param_init(void);
-extern errno_t bench_param_set(const char *, const char *);
-extern const char *bench_param_get(const char *, const char *);
-extern void bench_param_cleanup(void);
-
-#endif
-
-/** @}
- */
Index: uspace/app/perf/perf.c
===================================================================
--- uspace/app/perf/perf.c	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,395 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * Copyright (c) 2018 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/**
- * @file
- */
-
-#include <assert.h>
-#include <getopt.h>
-#include <math.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <str.h>
-#include <time.h>
-#include <errno.h>
-#include <str_error.h>
-#include <perf.h>
-#include <types/casting.h>
-#include "benchlist.h"
-#include "csv.h"
-#include "params.h"
-#include "perf.h"
-
-#define MIN_DURATION_SECS 10
-#define NUM_SAMPLES 10
-#define MAX_ERROR_STR_LENGTH 1024
-
-static void short_report(stopwatch_t *stopwatch, int run_index,
-    benchmark_t *bench, uint64_t workload_size)
-{
-	csv_report_add_entry(stopwatch, run_index, bench, workload_size);
-
-	usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(stopwatch));
-
-	printf("Completed %" PRIu64 " operations in %llu us",
-	    workload_size, duration_usec);
-	if (duration_usec > 0) {
-		double nanos = stopwatch_get_nanos(stopwatch);
-		double thruput = (double) workload_size / (nanos / 1000000000.0l);
-		printf(", %.0f ops/s.\n", thruput);
-	} else {
-		printf(".\n");
-	}
-}
-
-/*
- * This is a temporary solution until we have proper sqrt() implementation
- * in libmath.
- *
- * The algorithm uses Babylonian method [1].
- *
- * [1] https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
- */
-static double estimate_square_root(double value, double precision)
-{
-	double estimate = 1.;
-	double prev_estimate = estimate + 10 * precision;
-
-	while (fabs(estimate - prev_estimate) > precision) {
-		prev_estimate = estimate;
-		estimate = (prev_estimate + value / prev_estimate) / 2.;
-	}
-
-	return estimate;
-}
-
-/*
- * Compute available statistics from given stopwatches.
- *
- * We compute normal mean for average duration of the workload and geometric
- * mean for average thruput. Note that geometric mean is necessary to compute
- * average throughput correctly - consider the following example:
- *  - we run always 60 operations,
- *  - first run executes in 30 s (i.e. 2 ops/s)
- *  - and second one in 10 s (6 ops/s).
- * Then, naively, average throughput would be (2+6)/2 = 4 [ops/s]. However, we
- * actually executed 60 + 60 ops in 30 + 10 seconds. So the actual average
- * throughput is 3 ops/s (which is exactly what geometric mean means).
- *
- */
-static void compute_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
-    uint64_t workload_size, double precision, double *out_duration_avg,
-    double *out_duration_sigma, double *out_thruput_avg)
-{
-	double inv_thruput_sum = 0.0;
-	double nanos_sum = 0.0;
-	double nanos_sum2 = 0.0;
-
-	for (size_t i = 0; i < stopwatch_count; i++) {
-		double nanos = stopwatch_get_nanos(&stopwatch[i]);
-		double thruput = (double) workload_size / nanos;
-
-		inv_thruput_sum += 1.0 / thruput;
-		nanos_sum += nanos;
-		nanos_sum2 += nanos * nanos;
-	}
-	*out_duration_avg = nanos_sum / stopwatch_count;
-	double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) /
-	    ((double) stopwatch_count - 1);
-	// FIXME: implement sqrt properly
-	*out_duration_sigma = estimate_square_root(sigma2, precision);
-	*out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count);
-}
-
-static void summary_stats(stopwatch_t *stopwatch, size_t stopwatch_count,
-    benchmark_t *bench, uint64_t workload_size)
-{
-	double duration_avg, duration_sigma, thruput_avg;
-	compute_stats(stopwatch, stopwatch_count, workload_size, 0.001,
-	    &duration_avg, &duration_sigma, &thruput_avg);
-
-	printf("Average: %" PRIu64 " ops in %.0f us (sd %.0f us); "
-	    "%.0f ops/s; Samples: %zu\n",
-	    workload_size, duration_avg / 1000.0, duration_sigma / 1000.0,
-	    thruput_avg * 1000000000.0, stopwatch_count);
-}
-
-static bool run_benchmark(benchmark_t *bench)
-{
-	printf("Warm up and determine workload size...\n");
-
-	char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1);
-	if (error_msg == NULL) {
-		printf("Out of memory!\n");
-		return false;
-	}
-	str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "");
-
-	bool ret = true;
-
-	if (bench->setup != NULL) {
-		ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH);
-		if (!ret) {
-			goto leave_error;
-		}
-	}
-
-	/*
-	 * Find workload size that is big enough to last few seconds.
-	 * We also check that uint64_t is big enough.
-	 */
-	uint64_t workload_size = 0;
-	for (size_t bits = 0; bits <= 64; bits++) {
-		if (bits == 64) {
-			str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "Workload too small even for 1 << 63");
-			goto leave_error;
-		}
-		workload_size = ((uint64_t) 1) << bits;
-
-		stopwatch_t stopwatch = STOPWATCH_INITIALIZE_STATIC;
-
-		bool ok = bench->entry(&stopwatch, workload_size,
-		    error_msg, MAX_ERROR_STR_LENGTH);
-		if (!ok) {
-			goto leave_error;
-		}
-		short_report(&stopwatch, -1, bench, workload_size);
-
-		nsec_t duration = stopwatch_get_nanos(&stopwatch);
-		if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
-			break;
-		}
-	}
-
-	printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES);
-
-	stopwatch_t *stopwatch = calloc(NUM_SAMPLES, sizeof(stopwatch_t));
-	if (stopwatch == NULL) {
-		snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
-		goto leave_error;
-	}
-	for (int i = 0; i < NUM_SAMPLES; i++) {
-		stopwatch_init(&stopwatch[i]);
-
-		bool ok = bench->entry(&stopwatch[i], workload_size,
-		    error_msg, MAX_ERROR_STR_LENGTH);
-		if (!ok) {
-			free(stopwatch);
-			goto leave_error;
-		}
-		short_report(&stopwatch[i], i, bench, workload_size);
-	}
-
-	summary_stats(stopwatch, NUM_SAMPLES, bench, workload_size);
-	printf("\nBenchmark completed\n");
-
-	free(stopwatch);
-
-	goto leave;
-
-leave_error:
-	printf("Error: %s\n", error_msg);
-	ret = false;
-
-leave:
-	if (bench->teardown != NULL) {
-		bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH);
-		if (!ok) {
-			printf("Error: %s\n", error_msg);
-			ret = false;
-		}
-	}
-
-	free(error_msg);
-
-	return ret;
-}
-
-static int run_benchmarks(void)
-{
-	unsigned int count_ok = 0;
-	unsigned int count_fail = 0;
-
-	char *failed_names = NULL;
-
-	printf("\n*** Running all benchmarks ***\n\n");
-
-	for (size_t it = 0; it < benchmark_count; it++) {
-		printf("%s (%s)\n", benchmarks[it]->name, benchmarks[it]->desc);
-		if (run_benchmark(benchmarks[it])) {
-			count_ok++;
-			continue;
-		}
-
-		if (!failed_names) {
-			failed_names = str_dup(benchmarks[it]->name);
-		} else {
-			char *f = NULL;
-			asprintf(&f, "%s, %s", failed_names, benchmarks[it]->name);
-			if (!f) {
-				printf("Out of memory.\n");
-				abort();
-			}
-			free(failed_names);
-			failed_names = f;
-		}
-		count_fail++;
-	}
-
-	printf("\nCompleted, %u benchmarks run, %u succeeded.\n",
-	    count_ok + count_fail, count_ok);
-	if (failed_names)
-		printf("Failed benchmarks: %s\n", failed_names);
-
-	return count_fail;
-}
-
-static void list_benchmarks(void)
-{
-	size_t len = 0;
-	for (size_t i = 0; i < benchmark_count; i++) {
-		size_t len_now = str_length(benchmarks[i]->name);
-		if (len_now > len)
-			len = len_now;
-	}
-
-	assert(can_cast_size_t_to_int(len) && "benchmark name length overflow");
-
-	for (size_t i = 0; i < benchmark_count; i++)
-		printf("  %-*s %s\n", (int) len, benchmarks[i]->name, benchmarks[i]->desc);
-
-	printf("  %-*s Run all benchmarks\n", (int) len, "*");
-}
-
-static void print_usage(const char *progname)
-{
-	printf("Usage: %s [options] <benchmark>\n", progname);
-	printf("-h, --help                 "
-	    "Print this help and exit\n");
-	printf("-o, --output filename.csv  "
-	    "Store machine-readable data in filename.csv\n");
-	printf("-p, --param KEY=VALUE      "
-	    "Additional parameters for the benchmark\n");
-	printf("<benchmark> is one of the following:\n");
-	list_benchmarks();
-}
-
-static void handle_param_arg(char *arg)
-{
-	char *value = NULL;
-	char *key = str_tok(arg, "=", &value);
-	bench_param_set(key, value);
-}
-
-int main(int argc, char *argv[])
-{
-	errno_t rc = bench_param_init();
-	if (rc != EOK) {
-		fprintf(stderr, "Failed to initialize internal params structure: %s\n",
-		    str_error(rc));
-		return -5;
-	}
-
-	const char *short_options = "ho:p:";
-	struct option long_options[] = {
-		{ "help", optional_argument, NULL, 'h' },
-		{ "param", required_argument, NULL, 'p' },
-		{ "output", required_argument, NULL, 'o' },
-		{ 0, 0, NULL, 0 }
-	};
-
-	char *csv_output_filename = NULL;
-
-	int opt = 0;
-	while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) > 0) {
-		switch (opt) {
-		case 'h':
-			print_usage(*argv);
-			return 0;
-		case 'o':
-			csv_output_filename = optarg;
-			break;
-		case 'p':
-			handle_param_arg(optarg);
-			break;
-		case -1:
-		default:
-			break;
-		}
-	}
-
-	if (optind + 1 != argc) {
-		print_usage(*argv);
-		fprintf(stderr, "Error: specify one benchmark to run or * for all.\n");
-		return -3;
-	}
-
-	const char *benchmark = argv[optind];
-
-	if (csv_output_filename != NULL) {
-		errno_t rc = csv_report_open(csv_output_filename);
-		if (rc != EOK) {
-			fprintf(stderr, "Failed to open CSV report '%s': %s\n",
-			    csv_output_filename, str_error(rc));
-			return -4;
-		}
-	}
-
-	int exit_code = 0;
-
-	if (str_cmp(benchmark, "*") == 0) {
-		exit_code = run_benchmarks();
-	} else {
-		bool benchmark_exists = false;
-		for (size_t i = 0; i < benchmark_count; i++) {
-			if (str_cmp(benchmark, benchmarks[i]->name) == 0) {
-				benchmark_exists = true;
-				exit_code = run_benchmark(benchmarks[i]) ? 0 : -1;
-				break;
-			}
-		}
-		if (!benchmark_exists) {
-			printf("Unknown benchmark \"%s\"\n", benchmark);
-			exit_code = -2;
-		}
-	}
-
-	csv_report_close();
-	bench_param_cleanup();
-
-	return exit_code;
-}
-
-/** @}
- */
Index: uspace/app/perf/perf.h
===================================================================
--- uspace/app/perf/perf.h	(revision 1bad5fdb3bb0d0b9b92d3f625a69e8239786563f)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2018 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup perf
- * @{
- */
-/** @file
- */
-
-#ifndef PERF_H_
-#define PERF_H_
-
-#include <stdbool.h>
-#include <perf.h>
-
-typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t,
-    char *, size_t);
-typedef bool (*benchmark_helper_t)(char *, size_t);
-
-typedef struct {
-	const char *name;
-	const char *desc;
-	benchmark_entry_t entry;
-	benchmark_helper_t setup;
-	benchmark_helper_t teardown;
-} benchmark_t;
-
-#endif
-
-/** @}
- */
