diff --git a/bench/main.hs b/bench/main.hs
--- a/bench/main.hs
+++ b/bench/main.hs
@@ -36,8 +36,8 @@
     Right (i, "") -> Just i
     _ -> Nothing
 
-test :: Path '[] Maybe Int
-test = root $ exact "foo" $
+largePath :: Path '[] Maybe Int
+largePath = root $ exact "foo" $
     r p0 $ r p1 $ r p2 $ r p3 $ r p4 $
     r p5 $ r p6 $ r p7 $ r p8 $ r p9 $
     r p10 $ r p11 $ r p12 $ r p13 $ r p14 $
@@ -50,16 +50,53 @@
   where
     r p = fetch p readInt
 
-route :: Router '[] Maybe Int
-route = test +| empty
+largePathRoute :: Router '[] Maybe Int
+largePathRoute = largePath +| empty
 
-testPath :: [T.Text]
-testPath = "foo" : map (T.pack . show) [0..19::Int]
+testLargePath :: [T.Text]
+testLargePath = "foo" : map (T.pack . show) [0..19::Int]
 
+benchLargePath :: [T.Text] -> Maybe Int
+benchLargePath = execute largePathRoute "GET"
+
+testRoute :: Router '[] Maybe T.Text
+testRoute =
+    hello +| param +| (foldr (\i r -> deep i +| r) (after +| empty) [0..100])
+  where
+    hello = exact "echo" $ exact "hello-world" $ action (Just "GET") $ \_ -> Just "Hello World"
+
+    pS = Proxy :: Proxy "S"
+    pI = Proxy :: Proxy "I"
+    param = exact "echo" $ exact "plain" $ fetch pS Just $ fetch pI readInt $ action (Just "GET") $ \d ->
+        Just $ T.replicate (get pI d) (get pS d)
+
+    deep i = exact "deep" $ exact "foo" $ exact "bar" $ exact "baz" $ exact (T.pack $ show i) $ action (Just "GET") $ \_ ->
+        Just (T.pack $ show (i :: Int))
+
+    after = exact "after" $ action (Just "GET") $ \_ -> Just "after"
+
+benchApiaryBenchmark :: [T.Text] -> Maybe T.Text
+benchApiaryBenchmark = execute testRoute "GET"
+
 main :: IO ()
 main = do
-    unless ((execute route "GET") testPath == Just 190) $
-        fail "result not matched"
+    unless (benchLargePath testLargePath == Just 190) $ fail "largePath: result not matched"
+
+    let hello = ["echo", "hello-world"]
+        param = ["echo", "plain", "foo", "12"]
+        deep  = ["deep", "foo", "bar", "baz", "100"]
+        after = ["after"]
+    unless (benchApiaryBenchmark hello == Just "Hello World") $ fail "hello: result not matched"
+    unless (benchApiaryBenchmark param == Just (T.replicate 12 "foo")) $ fail "param: result not matched"
+    unless (benchApiaryBenchmark deep  == Just "100") $ fail "deep: result not matched"
+    unless (benchApiaryBenchmark after == Just "after") $ fail "after: result not matched"
+    
     defaultMain
-        [ bench "routing" $ nf (execute route "GET") testPath
+        [ bench "largePath" $ nf benchLargePath testLargePath
+        , bgroup "apiary"
+            [ bench "hello" $ nf benchApiaryBenchmark hello
+            , bench "param" $ nf benchApiaryBenchmark param
+            , bench "deep"  $ nf benchApiaryBenchmark deep
+            , bench "after" $ nf benchApiaryBenchmark after 
+            ]
         ]
diff --git a/src/Network/Routing.hs b/src/Network/Routing.hs
--- a/src/Network/Routing.hs
+++ b/src/Network/Routing.hs
@@ -63,6 +63,7 @@
     ( Method
       -- * Path 
     , Path
+    , showPath, getMethod
     , root
       -- ** children
     , exact
@@ -119,19 +120,19 @@
 type Method = S.ByteString
 
 data Params d m a where
-    PCons :: (D.Store d -> [T.Text] -> m (D.Store d', [T.Text]))
-          -> Router d' m a
-          -> Params d m a -> Params d m a
+    PCons :: !(D.Store d -> [T.Text] -> m (D.Store d', [T.Text]))
+          -> !(Router d' m a)
+          -> !(Params d m a) -> Params d m a
     PNil  :: Params d m a
 
 -- | routing path
 data Path d m a where
-    Exact :: T.Text -> Path d m a -> Path d m a
+    Exact :: !T.Text -> !(Path d m a) -> Path d m a
 
-    Param :: String -> (D.Store d -> [T.Text] -> m (D.Store d', [T.Text]))
-          -> Path d' m a -> Path d m a
+    Param :: !String -> (D.Store d -> [T.Text] -> m (D.Store d', [T.Text]))
+          -> !(Path d' m a) -> Path d m a
 
-    Action :: Maybe Method
+    Action :: !(Maybe Method)
            -> (D.Dict d -> m a) -> Path d m a
 
 -- | root
@@ -141,10 +142,12 @@
 -- @
 root :: Path '[] m a -> Path '[] m a
 root = id
+{-# INLINABLE root #-}
 
 -- | exact matching path
 exact :: T.Text -> Path d m a -> Path d m a
 exact = Exact
+{-# INLINABLE exact #-}
 
 type Raw m d d'
     = D.Store d -- ^ input dictionary
@@ -158,6 +161,7 @@
     -> Raw m d d'
     -> Path d' m a -> Path d m a
 raw = Param
+{-# INLINABLE raw #-}
 
 -- ^ get one directory as parameter.
 fetch :: (MonadPlus m, KnownSymbol k, k D.</ d)
@@ -170,12 +174,14 @@
     go d (t:ts) = case f t of
         Nothing -> mzero
         Just v  -> return (D.add p v d, ts)
+{-# INLINABLE fetch #-}
 
 -- | drop any pathes
 any :: Monad m => Path d m a -> Path d m a
 any = Param "**" go
   where
     go d _ = return (d, [])
+{-# INLINABLE any #-}
 
 -- | take any pathes as [Text]
 rest :: (KnownSymbol k, Monad m, k D.</ d) => proxy k -- ^ dictionary key
@@ -183,27 +189,42 @@
 rest k = Param (':': symbolVal k ++ "**") go
   where
     go d r = return (D.add k r d, [])
+{-# INLINABLE rest #-}
 
 -- | action
 action :: Maybe Method -- ^ if Nothing, any method allowed
        -> (D.Dict d -> m a) -- ^ action when route matching
        -> Path d m a
 action  = Action
+{-# INLINABLE action #-}
 
 instance Show (Path d m a) where
-    show = go id
-      where
-        go :: (String -> String) -> Path d m a -> String
-        go s (Exact t ps) = go (s . (++) ('/' : T.unpack t)) ps
-        go s (Param l _ ps) = go (s . (++) ('/': l)) ps
-        go s (Action m _) = maybe "*" SC.unpack m ++ ' ': s []
+    show p = maybe "*" SC.unpack (getMethod p) ++ ' ': showPath p
 
+-- | show path. since v0.6.0.
+showPath :: Path d m a -> String
+showPath = go id
+  where
+    go :: (String -> String) -> Path d m a -> String
+    go s (Exact t   ps) = go (s . (++) ('/' : T.unpack t)) ps
+    go s (Param l _ ps) = go (s . (++) ('/' : l)) ps
+    go s (Action _ _)   = s []
+
+-- | get method. since v0.6.0.
+getMethod :: Path d m a -> Maybe Method
+getMethod = go
+  where
+    go :: Path d m a -> Maybe Method
+    go (Action m _)   = m
+    go (Exact _   ps) = go ps
+    go (Param _ _ ps) = go ps
+
 -- | router
 data Router d m a where
     Router ::
-        { params    :: Params d m a
-        , children  :: H.HashMap T.Text (Router d m a)
-        , methods   :: H.HashMap Method (D.Dict d -> m a)
+        { params    :: !(Params d m a)
+        , children  :: !(H.HashMap T.Text (Router d m a))
+        , methods   :: !(H.HashMap Method (D.Dict d -> m a))
         , anyMethod :: D.Dict d -> m a
         } -> Router d m a
 
@@ -213,64 +234,73 @@
                      , methods   = H.empty
                      , anyMethod = const mzero
                      }
+{-# INLINABLE emptyRouter #-}
 
 -- | empty router
 empty :: MonadPlus m => Router '[] m a
 empty = emptyRouter
+{-# INLINABLE empty #-}
 
-add' :: MonadPlus m => Path d m a -> Router d m a -> Router d m a
-add' (Exact p n) r =
+insert' :: MonadPlus m => Path d m a -> Router d m a -> Router d m a
+insert' (Exact p n) r =
     let c = H.lookupDefault emptyRouter p (children r)
-    in r { children = H.insert p (add' n c) (children r) }
+    in r { children = H.insert p (insert' n c) (children r) }
 
-add' (Param _ f n) Router{..} = Router
-    { params    = PCons f (add' n emptyRouter) params
+insert' (Param _ f n) Router{..} = Router
+    { params    = PCons f (insert' n emptyRouter) params
     , children  = children
     , methods   = methods
     , anyMethod = anyMethod
     }
 
-add' (Action (Just m) n) r = 
+insert' (Action (Just m) n) r = 
     let c = case H.lookup m (methods r) of
             Nothing -> \d -> n d
             Just p  -> \d -> p d `mplus` n d
     in r { methods = H.insert m c (methods r) }
 
-add' (Action Nothing n) r =
+insert' (Action Nothing n) r =
     r { anyMethod = \d -> anyMethod r d `mplus` n d }
+{-# INLINABLE insert' #-}
 
 -- | insert path to router
 insert :: MonadPlus m => Path '[] m a -> Router '[] m a -> Router '[] m a
-insert = add'
+insert = insert'
+{-# INLINABLE insert #-}
 
 -- | infix version of `insert`
 (+|) :: MonadPlus m => Path '[] m a -> Router '[] m a -> Router '[] m a
 (+|) = insert
+{-# INLINABLE (+|) #-}
 
 infixr `insert`
 infixr +|
 
 -- | execute router
 execute :: MonadPlus m => Router '[] m a -> Method -> [T.Text] -> m a
-execute = execute' D.emptyStore
+execute = {-# SCC execute #-} execute' D.emptyStore
+{-# INLINABLE execute #-}
 
 execute' :: MonadPlus m => D.Store d -> Router d m a -> Method -> [T.Text] -> m a
-execute' d Router{params, methods, anyMethod} m [] = fetching d m [] params `mplus`
-    case H.lookup m methods of
+execute' d Router{params, methods, anyMethod} m [] = {-# SCC execute' #-} fetching next d m [] params
+  where
+    next = case H.lookup m methods of
         Nothing -> anyMethod (D.mkDict d)
         Just f  -> f (D.mkDict d)
 
-execute' d Router{params, children} m pps@(p:ps) = child `mplus` fetching d m pps params
+execute' d Router{params, children} m pps@(p:ps) = {-# SCC execute' #-} case H.lookup p children of
+    Nothing -> next
+    Just c  -> execute' d c m ps `mplus` next
   where
-    child = case H.lookup p children of
-        Nothing -> mzero
-        Just c  -> execute' d c m ps
+    next = fetching mzero d m pps params
+{-# INLINABLE execute' #-}
 
-fetching :: MonadPlus m => D.Store d -> Method -> [T.Text] -> Params d m a -> m a
-fetching d m pps = loop
+fetching :: MonadPlus m => m a -> D.Store d -> Method -> [T.Text] -> Params d m a -> m a
+fetching next d m pps = {-# SCC fetching #-} loop
   where
-    loop PNil = mzero
+    loop PNil = next
     loop (PCons f r o) =
         do (d', pps') <- f d pps
            execute' d' r m pps'
         `mplus` loop o
+{-# INLINABLE fetching #-}
diff --git a/src/Network/Routing/Dict/Internal.hs b/src/Network/Routing/Dict/Internal.hs
--- a/src/Network/Routing/Dict/Internal.hs
+++ b/src/Network/Routing/Dict/Internal.hs
@@ -41,9 +41,11 @@
 
 unsafeToAny :: a -> Any
 unsafeToAny = unsafeCoerce
+{-# INLINABLE unsafeToAny #-}
 
 unsafeFromAny :: Any -> a
 unsafeFromAny = unsafeCoerce
+{-# INLINABLE unsafeFromAny #-}
 
 -- | (kind) key-value pair
 data KV v = Symbol := v
@@ -67,9 +69,11 @@
 
 emptyStore :: Store '[]
 emptyStore = Store 0 Empty
+{-# INLINABLE emptyStore #-}
 
 emptyDict :: Dict '[]
 emptyDict = mkDict emptyStore
+{-# INLINABLE emptyDict #-}
 
 -- | (kind) pretty print type error of 'add'.
 --
@@ -105,6 +109,7 @@
 -- Store {bar = "baz" :: [Char], foo = 12 :: Int}
 add :: (k </ kvs) => proxy k -> v -> Store kvs -> Store (k := v ': kvs)
 add _ v (Store l c) = Store (l + 1) (Cons v c)
+{-# INLINABLE add #-}
 
 -- | heterogeneous dictionary
 --
@@ -141,10 +146,12 @@
             P.writeArray array i (unsafeToAny v)
             loop (i + 1) ss
         loop _ Empty = return ()
+{-# INLINABLE mkDict' #-}
 
 -- | O(n) convert "Store" to "Dictionary".
 mkDict :: Store kvs -> Dict kvs
 mkDict store = runST $ mkDict' store
+{-# INLINABLE mkDict #-}
 
 -- | O(1) (>= ghc-7.8), O(n) (< ghc-7.8) get key from dictionary
 --
@@ -180,6 +187,7 @@
 
 getImpl :: forall i proxy k kvs v. (Index i ~ Ix k kvs, KnownNat i) => proxy (k :: Symbol) -> Dict kvs -> v
 getImpl _ (Dict d) = unsafeFromAny $ d `P.indexArray` fromIntegral (natVal (Proxy :: Proxy i))
+{-# INLINABLE getImpl #-}
 
 class Member (k :: Symbol) (v :: *) (kvs :: [KV *]) | k kvs -> v where
     get' :: proxy k -> Dict kvs -> v
@@ -199,9 +207,11 @@
 
 instance Member k v (k := v ': kvs) where
     get' !i _ (Dict d) = unsafeFromAny $ d `P.indexArray` i
+    {-# INLINE get' #-}
 
 instance Member k v kvs => Member k v (k' := v' ': kvs) where
     get' !i k d = get' (i + 1) k (unsafeCoerce d :: Dict kvs)
+    {-# INLINE get' #-}
 
 get = get' 0
 #endif
diff --git a/web-routing.cabal b/web-routing.cabal
--- a/web-routing.cabal
+++ b/web-routing.cabal
@@ -1,7 +1,6 @@
 name:                web-routing
-version:             0.5.0
+version:             0.6.0
 synopsis:            simple routing library
--- description:         
 license:             MIT
 license-file:        LICENSE
 author:              HirotomoMoriwaki<philopon.dependence@gmail.com>
