diff --git a/src/benchmark.c b/src/benchmark.c
index 8105df3f4f60ff2af0e7640c2472e261c3b6766d..4d7c82503ca7728534ba86cc4c27f5b13cdf4dc0 100644
--- a/src/benchmark.c
+++ b/src/benchmark.c
@@ -1,19 +1,10 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <time.h>
 #include <string.h>
 #include "hammer.h"
 #include "internal.h"
-
-#ifdef __MACH__
-#include <mach/clock.h>
-#include <mach/mach.h>
-#endif
-
-#ifdef __NetBSD__
-#include <sys/resource.h>
-#endif
+#include "platform.h"
 
 static const char* HParserBackendNames[] = {
   "Packrat",
@@ -23,38 +14,6 @@ static const char* HParserBackendNames[] = {
   "GLR"
 };
 
-void h_benchmark_clock_gettime(struct timespec *ts) {
-  if (ts == NULL)
-    return;
-#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
-  /* 
-   * This returns real time, not CPU time. See http://stackoverflow.com/a/6725161
-   * Possible solution: http://stackoverflow.com/a/11659289
-   */
-  clock_serv_t cclock;
-  mach_timespec_t mts;
-  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
-  clock_get_time(cclock, &mts);
-  mach_port_deallocate(mach_task_self(), cclock);
-  ts->tv_sec = mts.tv_sec;
-  ts->tv_nsec = mts.tv_nsec;
-#elif defined(__NetBSD__)
-  // NetBSD doesn't have CLOCK_THREAD_CPUTIME_ID. We'll use getrusage instead
-  struct rusage rusage;
-  getrusage(RUSAGE_SELF, &rusage);
-  ts->tv_nsec = (rusage.ru_utime.tv_usec + rusage.ru_stime.tv_usec) * 1000;
-  // not going to overflow; can be at most 2e9-2
-  ts->tv_sec = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_sec;
-  if (ts->tv_nsec >= 1000000000) {
-    ts->tv_nsec -=   1000000000; // subtract a second
-    ts->tv_sec += 1; // add it back.
-  }
-  assert (ts->tv_nsec <= 1000000000);
-#else
-  clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts);
-#endif
-}
-
 /*
   Usage:
   Create your parser (i.e., const HParser*), and an array of test cases
@@ -76,6 +35,7 @@ HBenchmarkResults *h_benchmark(HParser* parser, HParserTestcase* testcases) {
   return h_benchmark__m(&system_allocator, parser, testcases);
 }
 
+//TODO(uucidl): replace tabs with the right number of spaces
 HBenchmarkResults *h_benchmark__m(HAllocator* mm__, HParser* parser, HParserTestcase* testcases) {
   // For now, just output the results to stderr
   HParserTestcase* tc = testcases;
@@ -135,20 +95,16 @@ HBenchmarkResults *h_benchmark__m(HAllocator* mm__, HParser* parser, HParserTest
 
     for (tc = testcases; tc->input != NULL; tc++) {
       // The goal is to run each testcase for at least 50ms each
-      // TODO: replace this with a posix timer-based benchmark. (cf. timerfd_create, timer_create, setitimer)
       int count = 1, cur;
-      struct timespec ts_start, ts_end;
       int64_t time_diff;
       do {
 	count *= 2; // Yes, this means that the first run will run the function twice. This is fine, as we want multiple runs anyway.
-  h_benchmark_clock_gettime(&ts_start);
+	struct HStopWatch stopwatch;
+	h_platform_stopwatch_reset(&stopwatch);
 	for (cur = 0; cur < count; cur++) {
 	  h_parse_result_free(h_parse(parser, tc->input, tc->length));
 	}
-  h_benchmark_clock_gettime(&ts_end);
-
-	// time_diff is in ns
-	time_diff = (ts_end.tv_sec - ts_start.tv_sec) * 1000000000 + (ts_end.tv_nsec - ts_start.tv_nsec);
+	time_diff = h_platform_stopwatch_ns(&stopwatch);
       } while (time_diff < 100000000);
       ret->results[backend].cases[cur_case].parse_time = (time_diff / count);
       ret->results[backend].cases[cur_case].length = tc->length;
diff --git a/src/platform.h b/src/platform.h
index 0c05bfe2e7ada4e7f1c5f48c3d705a839a78730a..21760dd9322d3dc60cc66683a53d17a42cda58f0 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -8,6 +8,8 @@
 
 #include "compiler_specifics.h"
 
+#include <stdint.h>
+
 /* Error Reporting */
 
 /* BSD errx function, seen in err.h */
@@ -15,4 +17,39 @@ H_MSVC_DECLSPEC(noreturn) \
 void h_platform_errx(int err, const char* format, ...)	\
   H_GCC_ATTRIBUTE((noreturn, format (printf,2,3)));
 
+/* Time Measurement */
+
+struct HStopWatch; /* forward definition */
+
+/* initialize a stopwatch */
+void h_platform_stopwatch_reset(struct HStopWatch* stopwatch);
+
+/* return difference between last reset point and now */
+int64_t h_platform_stopwatch_ns(struct HStopWatch* stopwatch);
+
+/* Platform dependent definitions for HStopWatch */
+#if defined(_MSC_VER)
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+struct HStopWatch {
+  LARGE_INTEGER qpf;
+  LARGE_INTEGER start;
+};
+
+#else
+/* Unix like platforms */
+
+#include <time.h>
+
+struct HStopWatch {
+  struct timespec start;
+};
+
+#endif
+
 #endif
diff --git a/src/platform_bsdlike.c b/src/platform_bsdlike.c
index ebb38d9df55243c75774dbfd9789932ee8d9c650..7d892cf9c7c8a35dc795447f0d98664a997a51c6 100644
--- a/src/platform_bsdlike.c
+++ b/src/platform_bsdlike.c
@@ -3,8 +3,64 @@
 #include <err.h>
 #include <stdarg.h>
 
+#ifdef __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
+
+#ifdef __NetBSD__
+#include <sys/resource.h>
+#endif
+
 void h_platform_errx(int err, const char* format, ...) {
   va_list ap;
   va_start(ap, format);
   verrx(err, format, ap);
 }
+
+// TODO: replace this with a posix timer-based benchmark. (cf. timerfd_create, timer_create, setitimer)
+
+static void gettime(struct timespec *ts) {
+  if (ts == NULL)
+    return;
+#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
+  /*
+   * This returns real time, not CPU time. See http://stackoverflow.com/a/6725161
+   * Possible solution: http://stackoverflow.com/a/11659289
+   */
+  clock_serv_t cclock;
+  mach_timespec_t mts;
+  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+  clock_get_time(cclock, &mts);
+  mach_port_deallocate(mach_task_self(), cclock);
+  ts->tv_sec = mts.tv_sec;
+  ts->tv_nsec = mts.tv_nsec;
+#elif defined(__NetBSD__)
+  // NetBSD doesn't have CLOCK_THREAD_CPUTIME_ID. We'll use getrusage instead
+  struct rusage rusage;
+  getrusage(RUSAGE_SELF, &rusage);
+  ts->tv_nsec = (rusage.ru_utime.tv_usec + rusage.ru_stime.tv_usec) * 1000;
+  // not going to overflow; can be at most 2e9-2
+  ts->tv_sec = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_sec;
+  if (ts->tv_nsec >= 1000000000) {
+    ts->tv_nsec -=   1000000000; // subtract a second
+    ts->tv_sec += 1; // add it back.
+  }
+  assert (ts->tv_nsec <= 1000000000);
+#else
+  clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts);
+#endif
+}
+
+void h_platform_stopwatch_reset(struct HStopWatch* stopwatch) {
+  gettime(&stopwatch->start);
+}
+
+int64_t h_platform_stopwatch_ns(struct HStopWatch* stopwatch) {
+  struct timespec ts_now;
+  gettime(&ts_now);
+
+  // time_diff is in ns
+  return (ts_now.tv_sec - stopwatch->start.tv_sec) * 1000000000
+	  + (ts_now.tv_nsec - stopwatch->start.tv_nsec);
+}