diff --git a/include/mrbconf.h b/include/mrbconf.h
index bcef1b1..b31988e 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -59,6 +59,9 @@
 /* fixed size GC arena */
 //#define MRB_GC_FIXED_ARENA
 
+/* method cache */
+//#define MRB_METHOD_CACHE
+
 /* -DDISABLE_XXXX to drop following features */
 //#define DISABLE_STDIO		/* use of stdio */
 
diff --git a/include/mruby.h b/include/mruby.h
index e925502..ddd88d7 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -96,6 +96,19 @@ enum gc_state {
   GC_STATE_SWEEP
 };
 
+#ifdef MRB_METHOD_CACHE
+#define MRB_CACHE_SIZE 0x800
+#define MRB_CACHE_MASK 0x7ff
+#define MRB_CACHE(c,m) ((((((unsigned long)(void*)c))>>3)^(m))&MRB_CACHE_MASK)
+
+/* method hash table. */
+struct mrb_cache_entry {
+  mrb_sym mid;
+  struct RClass *c;
+  struct RProc* p;
+};
+#endif
+
 typedef struct mrb_state {
   void *jmp;
 
@@ -162,6 +175,10 @@ typedef struct mrb_state {
   struct RClass *eStandardError_class;
 
   void *ud; /* auxiliary data */
+
+#ifdef MRB_METHOD_CACHE
+  struct mrb_cache_entry cache[MRB_CACHE_SIZE];
+#endif
 } mrb_state;
 
 typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
diff --git a/src/class.c b/src/class.c
index d290892..c35e4f1 100644
--- a/src/class.c
+++ b/src/class.c
@@ -991,6 +991,14 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
   struct RProc *m;
   struct RClass *c = *cp;
 
+#ifdef MRB_METHOD_CACHE
+  struct mrb_cache_entry* ce;
+  ce = mrb->cache + MRB_CACHE(c, mid);
+  if (ce->c == c && ce->mid == mid) {
+    return ce->p;
+  }
+#endif
+
   while (c) {
     khash_t(mt) *h = c->mt;
 
@@ -999,6 +1007,11 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
       if (k != kh_end(h)) {
         m = kh_value(h, k);
         if (!m) break;
+#ifdef MRB_METHOD_CACHE
+        ce->mid = mid;
+        ce->c = *cp;
+        ce->p = m;
+#endif
         *cp = c;
         return m;
       }