diff --git a/benchtests/bench-malloc-thread.c b/benchtests/bench-malloc-thread.c
index 46fdabd30c..e8429cec10 100644
--- a/benchtests/bench-malloc-thread.c
+++ b/benchtests/bench-malloc-thread.c
@@ -123,6 +123,8 @@ alarm_handler (int signum)
   timeout = true;
 }
 
+typedef size_t (*loop_func_t)(void **);
+
 /* Allocate and free blocks in a random order.  */
 static size_t
 malloc_benchmark_loop (void **ptr_arr)
@@ -145,10 +147,32 @@ malloc_benchmark_loop (void **ptr_arr)
   return iters;
 }
 
+static size_t
+calloc_benchmark_loop (void **ptr_arr)
+{
+  unsigned int offset_state = 0, block_state = 0;
+  size_t iters = 0;
+
+  while (!timeout)
+    {
+      unsigned int next_idx = get_random_offset (&offset_state);
+      unsigned int next_block = get_random_block_size (&block_state);
+
+      free (ptr_arr[next_idx]);
+
+      ptr_arr[next_idx] = calloc (1, next_block);
+
+      iters++;
+    }
+
+  return iters;
+}
+
 struct thread_args
 {
   size_t iters;
   void **working_set;
+  loop_func_t benchmark_loop;
   timing_t elapsed;
 };
 
@@ -161,7 +185,7 @@ benchmark_thread (void *arg)
   timing_t start, stop;
 
   TIMING_NOW (start);
-  iters = malloc_benchmark_loop (thread_set);
+  iters = args->benchmark_loop (thread_set);
   TIMING_NOW (stop);
 
   TIMING_DIFF (args->elapsed, start, stop);
@@ -171,7 +195,7 @@ benchmark_thread (void *arg)
 }
 
 static timing_t
-do_benchmark (size_t num_threads, size_t *iters)
+do_benchmark (loop_func_t benchmark_loop, size_t num_threads, size_t *iters)
 {
   timing_t elapsed = 0;
 
@@ -183,7 +207,7 @@ do_benchmark (size_t num_threads, size_t *iters)
       memset (working_set, 0, sizeof (working_set));
 
       TIMING_NOW (start);
-      *iters = malloc_benchmark_loop (working_set);
+      *iters = benchmark_loop (working_set);
       TIMING_NOW (stop);
 
       TIMING_DIFF (elapsed, start, stop);
@@ -201,6 +225,7 @@ do_benchmark (size_t num_threads, size_t *iters)
       for (size_t i = 0; i < num_threads; i++)
 	{
 	  args[i].working_set = working_set[i];
+	  args[i].benchmark_loop = benchmark_loop;
 	  pthread_create(&threads[i], NULL, benchmark_thread, &args[i]);
 	}
 
@@ -214,6 +239,47 @@ do_benchmark (size_t num_threads, size_t *iters)
   return elapsed;
 }
 
+static void
+bench_function (json_ctx_t *json_ctx, size_t num_threads,
+  const char *func_name, loop_func_t benchmark_loop)
+{
+  timing_t cur;
+  size_t iters = 0;
+  double d_total_s, d_total_i;
+
+  init_random_values ();
+
+  json_attr_object_begin (json_ctx, func_name);
+
+  json_attr_object_begin (json_ctx, "");
+
+  timeout = false;
+  alarm (BENCHMARK_DURATION);
+
+  cur = do_benchmark (benchmark_loop, num_threads, &iters);
+
+  struct rusage usage;
+  getrusage(RUSAGE_SELF, &usage);
+
+  d_total_s = cur;
+  d_total_i = iters;
+
+  json_attr_double (json_ctx, "duration", d_total_s);
+  json_attr_double (json_ctx, "iterations", d_total_i);
+  json_attr_double (json_ctx, "time_per_iteration", d_total_s / d_total_i);
+  json_attr_double (json_ctx, "max_rss", usage.ru_maxrss);
+
+  json_attr_double (json_ctx, "threads", num_threads);
+  json_attr_double (json_ctx, "min_size", MIN_ALLOCATION_SIZE);
+  json_attr_double (json_ctx, "max_size", MAX_ALLOCATION_SIZE);
+  json_attr_double (json_ctx, "random_seed", RAND_SEED);
+
+  json_attr_object_end (json_ctx);
+
+  json_attr_object_end (json_ctx);
+
+}
+
 static void usage(const char *name)
 {
   fprintf (stderr, "%s: <num_threads>\n", name);
@@ -223,10 +289,8 @@ static void usage(const char *name)
 int
 main (int argc, char **argv)
 {
-  timing_t cur;
-  size_t iters = 0, num_threads = 1;
+  size_t num_threads = 1;
   json_ctx_t json_ctx;
-  double d_total_s, d_total_i;
   struct sigaction act;
 
   if (argc == 1)
@@ -246,48 +310,22 @@ main (int argc, char **argv)
   else
     usage(argv[0]);
 
-  init_random_values ();
-
-  json_init (&json_ctx, 0, stdout);
-
-  json_document_begin (&json_ctx);
-
-  json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
-
-  json_attr_object_begin (&json_ctx, "functions");
-
-  json_attr_object_begin (&json_ctx, "malloc");
-
-  json_attr_object_begin (&json_ctx, "");
-
   memset (&act, 0, sizeof (act));
   act.sa_handler = &alarm_handler;
 
   sigaction (SIGALRM, &act, NULL);
 
-  alarm (BENCHMARK_DURATION);
-
-  cur = do_benchmark (num_threads, &iters);
-
-  struct rusage usage;
-  getrusage(RUSAGE_SELF, &usage);
+  json_init (&json_ctx, 0, stdout);
 
-  d_total_s = cur;
-  d_total_i = iters;
+  json_document_begin (&json_ctx);
 
-  json_attr_double (&json_ctx, "duration", d_total_s);
-  json_attr_double (&json_ctx, "iterations", d_total_i);
-  json_attr_double (&json_ctx, "time_per_iteration", d_total_s / d_total_i);
-  json_attr_double (&json_ctx, "max_rss", usage.ru_maxrss);
+  json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
 
-  json_attr_double (&json_ctx, "threads", num_threads);
-  json_attr_double (&json_ctx, "min_size", MIN_ALLOCATION_SIZE);
-  json_attr_double (&json_ctx, "max_size", MAX_ALLOCATION_SIZE);
-  json_attr_double (&json_ctx, "random_seed", RAND_SEED);
+  json_attr_object_begin (&json_ctx, "functions");
 
-  json_attr_object_end (&json_ctx);
+  bench_function (&json_ctx, num_threads, "malloc", malloc_benchmark_loop);
 
-  json_attr_object_end (&json_ctx);
+  bench_function (&json_ctx, num_threads, "calloc", calloc_benchmark_loop);
 
   json_attr_object_end (&json_ctx);
 
