diff --git a/common.mk b/common.mk
index 57e80ddce26ef183d36664f3618f8bc0f9f92ce0..de00ecbf0e2f0f58ff033d547f85ce200b67883e 100644
--- a/common.mk
+++ b/common.mk
@@ -3,7 +3,7 @@ LDFLAGS := $(shell pkg-config --libs glib-2.0)
 CC := gcc
 # Set V=1 for verbose mode...
 V := 0
-CFLAGS += -DINCLUDE_TESTS
+CFLAGS += -DINCLUDE_TESTS $(EXTRA_CFLAGS)
 HUSH = $(TOPLEVEL)/lib/hush
 
 # Check to make sure variables are properly set
diff --git a/src/allocator.c b/src/allocator.c
index 77f14ea347d7a8f6c0f7da11a517e7b78ff25dab..c45affd45e7a9d7c507e6824968985306e88115c 100644
--- a/src/allocator.c
+++ b/src/allocator.c
@@ -20,17 +20,22 @@ struct arena_link {
 struct arena {
   struct arena_link *head;
   size_t block_size;
+  size_t used;
+  size_t wasted;
 };
 
 arena_t new_arena(size_t block_size) {
+  if (block_size == 0)
+    block_size = 4096;
   struct arena *ret = g_new(struct arena, 1);
   struct arena_link *link = (struct arena_link*)g_malloc0(sizeof(struct arena_link) + block_size);
   link->free = block_size;
   link->used = 0;
   link->next = NULL;
   ret->head = link;
-  ret->block_size = 0;
-
+  ret->block_size = block_size;
+  ret->used = 0;
+  ret->wasted = sizeof(struct arena_link) + sizeof(struct arena) + block_size;
   return ret;
 }
 
@@ -38,12 +43,16 @@ void* arena_malloc(arena_t arena, size_t size) {
   if (size <= arena->head->free) {
     // fast path..
     void* ret = arena->head->rest + arena->head->used;
+    arena->used += size;
+    arena->wasted -= size;
     arena->head->used += size;
     arena->head->free -= size;
     return ret;
   } else if (size > arena->block_size) {
     // We need a new, dedicated block for it, because it won't fit in a standard sized one.
     // This involves some annoying casting...
+    arena->used += size;
+    arena->wasted += sizeof(struct arena_link*);
     void* link = g_malloc(size + sizeof(struct arena_link*));
     *(struct arena_link**)link = arena->head->next;
     arena->head->next = (struct arena_link*)link;
@@ -55,6 +64,8 @@ void* arena_malloc(arena_t arena, size_t size) {
     link->used = size;
     link->next = arena->head;
     arena->head = link;
+    arena->used += size;
+    arena->wasted += sizeof(struct arena_link) + arena->block_size - size;
     return link->rest;
   }
 }
@@ -71,3 +82,8 @@ void delete_arena(arena_t arena) {
   }
   g_free(arena);
 }
+
+void allocator_stats(arena_t arena, arena_stats_t *stats) {
+  stats->used = arena->used;
+  stats->wasted = arena->wasted;
+}
diff --git a/src/allocator.h b/src/allocator.h
index 3bc7cedc44739424dd9ad7a9f9f7db6b5b0d51ad..4904b290b14c76bef9323e1ddde064019be3fea2 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -8,5 +8,12 @@ arena_t new_arena(size_t block_size); // pass 0 for default...
 void* arena_malloc(arena_t arena, size_t count) __attribute__(( malloc, alloc_size(2) ));
 void delete_arena(arena_t arena);
 
+typedef struct {
+  size_t used;
+  size_t wasted;
+} arena_stats_t;
+
+void allocator_stats(arena_t arena, arena_stats_t *stats);
+
 
 #endif // #ifndef LIB_ALLOCATOR__H__
diff --git a/src/hammer.c b/src/hammer.c
index 0e48b85cafd27a3d345dd62c064ac74f2f5f3980..ced1a23db2bb4aff1fdec64cd0dbb098520f0260 100644
--- a/src/hammer.c
+++ b/src/hammer.c
@@ -37,10 +37,9 @@ guint djbhash(const uint8_t *buf, size_t len) {
 
 parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) {
   // TODO(thequux): add caching here.
-  parser_cache_key_t key = {
-    .input_pos = state->input_stream,
-    .parser = parser
-  };
+  parser_cache_key_t *key = a_new(parser_cache_key_t, 1);
+  key->input_pos = state->input_stream;
+  key->parser = parser;
   
   // check to see if there is already a result for this object...
   if (g_hash_table_contains(state->cache, &key)) {
@@ -50,9 +49,11 @@ parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) {
   } else {
     // It doesn't exist... run the 
     parse_result_t *res;
-    if (parser)
+    if (parser) {
       res = parser->fn(parser->env, state);
-    else
+      if (res)
+	res->arena = state->arena;
+    } else
       res = NULL;
     if (state->input_stream.overrun)
       res = NULL; // overrun is always failure.
@@ -766,7 +767,10 @@ static void test_and(void) {
 
 static void test_not(void) {
   const parser_t *not_1 = sequence(ch('a'), choice(ch('+'), token((const uint8_t*)"++", 2), NULL), ch('b'), NULL);
-  const parser_t *not_2 = sequence(ch('a'), choice(sequence(ch('+'), not(ch('+')), NULL), token((const uint8_t*)"", 2), NULL), ch('b'), NULL);
+  const parser_t *not_2 = sequence(ch('a'),
+				   choice(sequence(ch('+'), not(ch('+')), NULL),
+					  token((const uint8_t*)"++", 2),
+					  NULL), ch('b'), NULL);
 
   g_check_parse_ok(not_1, "a+b", 3, "(s0x61 s0x2B s0x62)");
   g_check_parse_failed(not_1, "a++b", 4);
diff --git a/src/test_suite.h b/src/test_suite.h
index 47c5ac401f4a368b7ceba0642030d9f3aaaa0457..a67fa1f6cfe5b86babcd775d5c70d91755163543 100644
--- a/src/test_suite.h
+++ b/src/test_suite.h
@@ -54,11 +54,17 @@
 #define g_check_parse_ok(parser, input, inp_len, result) {		\
     parse_result_t *res = parse(parser, (const uint8_t*)input, inp_len); \
     if (!res) {								\
-      g_test_message("Parse failed on line %d", __LINE__);				\
+      g_test_message("Parse failed on line %d", __LINE__);		\
       g_test_fail();							\
     } else {								\
       char* cres = write_result_unamb(res->ast);			\
       g_check_string(cres, ==, result);					\
+      arena_stats_t stats;						\
+      allocator_stats(res->arena, &stats);				\
+      g_test_message("Parse used %zd bytes, wasted %zd bytes. "		\
+                     "Inefficiency: %5f%%",				\
+		     stats.used, stats.wasted,				\
+		     stats.wasted * 100. / (stats.used+stats.wasted));	\
     }									\
   }