Index: uspace/app/hbench/env.c
===================================================================
--- uspace/app/hbench/env.c	(revision 2d818807c3fd981ff6a5d2e7b7a21b28ec372bff)
+++ uspace/app/hbench/env.c	(revision 67bcd81c93cb3e140875fa93fd665f0383799e7c)
@@ -96,4 +96,7 @@
 	}
 
+	env->run_count = DEFAULT_RUN_COUNT;
+	env->minimal_run_duration_nanos = MSEC2NSEC(DEFAULT_MIN_RUN_DURATION_SEC);
+
 	return EOK;
 }
Index: uspace/app/hbench/hbench.h
===================================================================
--- uspace/app/hbench/hbench.h	(revision 2d818807c3fd981ff6a5d2e7b7a21b28ec372bff)
+++ uspace/app/hbench/hbench.h	(revision 67bcd81c93cb3e140875fa93fd665f0383799e7c)
@@ -42,4 +42,7 @@
 #include <perf.h>
 
+#define DEFAULT_RUN_COUNT 10
+#define DEFAULT_MIN_RUN_DURATION_SEC 10
+
 /** Single run information.
  *
@@ -60,8 +63,13 @@
 /** Benchmark environment configuration.
  *
- * Use proper access functions when modifying data inside this structure.
+ * Benchmarking code (runners) should use access functions to read
+ * data from this structure (now only bench_env_param_get).
+ *
+ * Harness can access it directly.
  */
 typedef struct {
 	hash_table_t parameters;
+	size_t run_count;
+	nsec_t minimal_run_duration_nanos;
 } bench_env_t;
 
Index: uspace/app/hbench/main.c
===================================================================
--- uspace/app/hbench/main.c	(revision 2d818807c3fd981ff6a5d2e7b7a21b28ec372bff)
+++ uspace/app/hbench/main.c	(revision 67bcd81c93cb3e140875fa93fd665f0383799e7c)
@@ -49,6 +49,4 @@
 #include "hbench.h"
 
-#define MIN_DURATION_SECS 10
-#define NUM_SAMPLES 10
 #define MAX_ERROR_STR_LENGTH 1024
 
@@ -131,5 +129,9 @@
 	    ((double) run_count - 1);
 	// FIXME: implement sqrt properly
-	*out_duration_sigma = estimate_square_root(sigma2, precision);
+	if (run_count > 1) {
+		*out_duration_sigma = estimate_square_root(sigma2, precision);
+	} else {
+		*out_duration_sigma = NAN;
+	}
 	*out_thruput_avg = 1.0 / (inv_thruput_sum / run_count);
 }
@@ -197,17 +199,18 @@
 
 		nsec_t duration = stopwatch_get_nanos(&run.stopwatch);
-		if (duration > SEC2NSEC(MIN_DURATION_SECS)) {
-			break;
-		}
-	}
-
-	printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES);
-
-	bench_run_t *runs = calloc(NUM_SAMPLES, sizeof(bench_run_t));
+		if (duration > env->minimal_run_duration_nanos) {
+			break;
+		}
+	}
+
+	printf("Workload size set to %" PRIu64 ", measuring %zu samples.\n",
+	    workload_size, env->run_count);
+
+	bench_run_t *runs = calloc(env->run_count, sizeof(bench_run_t));
 	if (runs == NULL) {
 		snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory");
 		goto leave_error;
 	}
-	for (int i = 0; i < NUM_SAMPLES; i++) {
+	for (size_t i = 0; i < env->run_count; i++) {
 		bench_run_init(&runs[i], error_msg, MAX_ERROR_STR_LENGTH);
 
@@ -220,5 +223,5 @@
 	}
 
-	summary_stats(runs, NUM_SAMPLES, bench, workload_size);
+	summary_stats(runs, env->run_count, bench, workload_size);
 	printf("\nBenchmark completed\n");
 
@@ -306,4 +309,8 @@
 	printf("-h, --help                 "
 	    "Print this help and exit\n");
+	printf("-d, --duration MILLIS      "
+	    "Set minimal run duration (milliseconds)\n");
+	printf("-n, --count N              "
+	    "Set number of measured runs\n");
 	printf("-o, --output filename.csv  "
 	    "Store machine-readable data in filename.csv\n");
@@ -331,9 +338,11 @@
 	}
 
-	const char *short_options = "ho:p:";
+	const char *short_options = "ho:p:n:d:";
 	struct option long_options[] = {
+		{ "duration", required_argument, NULL, 'd' },
 		{ "help", optional_argument, NULL, 'h' },
+		{ "count", required_argument, NULL, 'n' },
+		{ "output", required_argument, NULL, 'o' },
 		{ "param", required_argument, NULL, 'p' },
-		{ "output", required_argument, NULL, 'o' },
 		{ 0, 0, NULL, 0 }
 	};
@@ -344,7 +353,23 @@
 	while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) > 0) {
 		switch (opt) {
+		case 'd':
+			errno = EOK;
+			bench_env.minimal_run_duration_nanos = MSEC2NSEC(atoll(optarg));
+			if ((errno != EOK) || (bench_env.minimal_run_duration_nanos <= 0)) {
+				fprintf(stderr, "Invalid -d argument.\n");
+				return -3;
+			}
+			break;
 		case 'h':
 			print_usage(*argv);
 			return 0;
+		case 'n':
+			errno = EOK;
+			bench_env.run_count = (nsec_t) atoll(optarg);
+			if ((errno != EOK) || (bench_env.run_count <= 0)) {
+				fprintf(stderr, "Invalid -n argument.\n");
+				return -3;
+			}
+			break;
 		case 'o':
 			csv_output_filename = optarg;
