diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Stache 0.1.1
+
+* Added benchmarks.
+
 ## Stache 0.1.0
 
 * Initial release.
diff --git a/Text/Mustache/Type.hs b/Text/Mustache/Type.hs
--- a/Text/Mustache/Type.hs
+++ b/Text/Mustache/Type.hs
@@ -12,6 +12,7 @@
 -- module instead.
 
 {-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
 module Text.Mustache.Type
@@ -22,6 +23,7 @@
   , MustacheException (..) )
 where
 
+import Control.DeepSeq
 import Control.Monad.Catch (Exception)
 import Data.Data (Data)
 import Data.Map (Map)
@@ -29,6 +31,7 @@
 import Data.String (IsString (..))
 import Data.Text (Text)
 import Data.Typeable (Typeable)
+import GHC.Generics
 import Text.Megaparsec
 import qualified Data.Map  as M
 import qualified Data.Text as T
@@ -48,7 +51,7 @@
     -- ^ Collection of all templates that are available for interpolation
     -- (as partials). The top-level one is also contained here and the
     -- “focus” can be switched easily by modifying 'templateActual'.
-  } deriving (Eq, Ord, Show, Data, Typeable)
+  } deriving (Eq, Ord, Show, Data, Typeable, Generic)
 
 instance Semigroup Template where
   (Template pname x) <> (Template _ y) = Template pname (M.union x y)
@@ -63,7 +66,7 @@
   | InvertedSection Key [Node] -- ^ Inverted section
   | Partial         PName (Maybe Pos)
     -- ^ Partial with indentation level ('Nothing' means it was inlined)
-  deriving (Eq, Ord, Show, Data, Typeable)
+  deriving (Eq, Ord, Show, Data, Typeable, Generic)
 
 -- | Identifier for values to interpolate.
 --
@@ -74,20 +77,24 @@
 --     * @[text1, text2]@ — multiple keys represent dotted names.
 
 newtype Key = Key { unKey :: [Text] }
-  deriving (Eq, Ord, Show, Monoid, Data, Typeable)
+  deriving (Eq, Ord, Show, Monoid, Data, Typeable, Generic)
 
+instance NFData Key
+
 -- | Identifier for partials. Note that with the @OverloadedStrings@
 -- extension you can use just string literals to create values of this type.
 
 newtype PName = PName { unPName :: Text }
-  deriving (Eq, Ord, Show, Data, Typeable)
+  deriving (Eq, Ord, Show, Data, Typeable, Generic)
 
 instance IsString PName where
   fromString = PName . T.pack
 
+instance NFData PName
+
 -- | Exception that is thrown when parsing of a template has failed.
 
 data MustacheException = MustacheException (ParseError Char Dec)
-  deriving (Eq, Show, Typeable)
+  deriving (Eq, Show, Typeable, Generic)
 
 instance Exception MustacheException
diff --git a/bench-data/comprehensive.mustache b/bench-data/comprehensive.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/comprehensive.mustache
@@ -0,0 +1,18 @@
+This is a comprehensive example of Mustache template.
+
+It has {{first-thing}} and {{&second-thing}}, as well as a bit of
+{{third-thing}}.
+
+John has the following items today:
+{{#items}}
+  * {{.}}
+{{/items}}
+{{^items}}
+  None.
+{{/items}}
+
+We could also use this text as a start of our conversation:
+
+{{> lorem-ipsum}}
+
+But we won't.
diff --git a/bench-data/escaped-var.mustache b/bench-data/escaped-var.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/escaped-var.mustache
@@ -0,0 +1,1 @@
+This is text with {{escaped-variable}}, you know.
diff --git a/bench-data/inverted-section.mustache b/bench-data/inverted-section.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/inverted-section.mustache
@@ -0,0 +1,3 @@
+{{^section}}
+  This is section with some text in it.
+{{/section}}
diff --git a/bench-data/lorem-ipsum.mustache b/bench-data/lorem-ipsum.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/lorem-ipsum.mustache
@@ -0,0 +1,38 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio.
+Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at
+nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec
+tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget
+nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra,
+per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim
+lacinia nunc.
+
+Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at
+dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel
+nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis,
+luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris
+ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh.
+Quisque volutpat condimentum velit.
+
+Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
+inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis,
+tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla
+facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus
+consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices.
+Suspendisse in justo eu magna luctus suscipit.
+
+Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae
+pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam.
+Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere
+cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non
+quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet
+pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas
+et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim.
+Curabitur sit amet mauris.
+
+Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia
+sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam.
+Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices
+sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet.
+Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut
+orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed
+pretium blandit orci.
diff --git a/bench-data/nested-sections.mustache b/bench-data/nested-sections.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/nested-sections.mustache
@@ -0,0 +1,11 @@
+{{#section-a}}
+Section A begins.
+  {{#section-b}}
+  Section B begins.
+    {{#section-c}}
+    And this is the C section.
+    {{/section-c}}
+  Section B ends.
+  {{/section-b}}
+Section A ends.
+{{/section-a}}
diff --git a/bench-data/partial.mustache b/bench-data/partial.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/partial.mustache
@@ -0,0 +1,3 @@
+And here we have partial:
+  {{> lorem-ipsum}}
+End.
diff --git a/bench-data/section.mustache b/bench-data/section.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/section.mustache
@@ -0,0 +1,3 @@
+{{#section}}
+  This is section with some text in it.
+{{/section}}
diff --git a/bench-data/unescaped-var-spec.mustache b/bench-data/unescaped-var-spec.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/unescaped-var-spec.mustache
@@ -0,0 +1,1 @@
+This is text with {{{unescaped-variable}}}, you know.
diff --git a/bench-data/unescaped-var.mustache b/bench-data/unescaped-var.mustache
new file mode 100644
--- /dev/null
+++ b/bench-data/unescaped-var.mustache
@@ -0,0 +1,1 @@
+This is text with {{&unescaped-variable}}, you know.
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE CPP                  #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Main (main) where
+
+import Control.DeepSeq
+import Criterion.Main
+import Data.Aeson
+import Data.Text (Text)
+import Text.Megaparsec
+import Text.Mustache.Compile
+import Text.Mustache.Parser
+import Text.Mustache.Render
+import Text.Mustache.Type
+import qualified Data.Text.Lazy.IO as T
+
+----------------------------------------------------------------------------
+-- Benchmarks
+
+main :: IO ()
+main = defaultMain [ parserBench, renderBench ]
+
+parserBench :: Benchmark
+parserBench = bgroup "parser"
+  [ bparser "simple block of text"
+      "bench-data/lorem-ipsum.mustache"
+  , bparser "text with escaped var"
+      "bench-data/escaped-var.mustache"
+  , bparser "text with unescaped var"
+      "bench-data/unescaped-var.mustache"
+  , bparser "text with unescaped var special"
+      "bench-data/unescaped-var-spec.mustache"
+  , bparser "a section"
+      "bench-data/section.mustache"
+  , bparser "an inverted section"
+      "bench-data/inverted-section.mustache"
+  , bparser "nested sections"
+      "bench-data/nested-sections.mustache"
+  , bparser "text with partial"
+      "bench-data/partial.mustache"
+  , bparser "comprehensive template"
+      "bench-data/comprehensive.mustache"
+  ]
+
+renderBench :: Benchmark
+renderBench = bgroup "render"
+  [ brender "simple block of text"
+      "bench-data/lorem-ipsum.mustache"
+      Null
+  , brender "text with escaped var"
+      "bench-data/escaped-var.mustache"
+      (object ["escaped-variable" .= ("escaped variable" :: Text)])
+  , brender "text with unescaped var"
+      "bench-data/unescaped-var.mustache"
+      (object ["unescaped-variable" .= ("unescaped variable" :: Text)])
+  , brender "text with unescaped var special"
+      "bench-data/unescaped-var-spec.mustache"
+      (object ["unescaped-variable" .= ("unescaped variable" :: Text)])
+  , brender "a section"
+      "bench-data/section.mustache"
+      (object ["section" .= True])
+  , brender "an inverted section"
+      "bench-data/inverted-section.mustache"
+      (object ["section" .= False])
+  , brender "nested sections"
+      "bench-data/nested-sections.mustache"
+      (object [ "section-a" .= True
+              , "section-b" .= True
+              , "section-c" .= True ])
+  , brender' "text with partial"
+      "bench-data/" "partial"
+      Null
+  , brender' "comprehensive template"
+      "bench-data/" "comprehensive"
+      (object [ "first-thing"  .= ("the first thing" :: Text)
+              , "second-thing" .= ("the second thing" :: Text)
+              , "third-thing"  .= ("the third thing" :: Text)
+              , "items" .= [1..10 :: Int] ])
+  ]
+
+bparser :: String -> FilePath -> Benchmark
+bparser desc path = env (T.readFile path)
+  (bench desc . nf (either (error . parseErrorPretty) id . parseMustache path))
+
+brender :: String -> FilePath -> Value -> Benchmark
+brender desc path value = env (compileMustacheFile path)
+  (bench desc . nf (`renderMustache` value))
+
+brender' :: String -> FilePath -> PName -> Value -> Benchmark
+brender' desc path pname value = env (compileMustacheDir pname path)
+  (bench desc . nf (`renderMustache` value))
+
+----------------------------------------------------------------------------
+-- Orphan instances
+
+instance NFData Pos where
+  rnf = rnf . unPos
+
+instance NFData Node
+
+instance NFData Template
diff --git a/stache.cabal b/stache.cabal
--- a/stache.cabal
+++ b/stache.cabal
@@ -31,7 +31,7 @@
 -- POSSIBILITY OF SUCH DAMAGE.
 
 name:                 stache
-version:              0.1.0
+version:              0.1.1
 cabal-version:        >= 1.10
 license:              BSD3
 license-file:         LICENSE.md
@@ -45,14 +45,23 @@
 description:          Mustache templates for Haskell.
 extra-source-files:   CHANGELOG.md
                     , README.md
+                    , bench-data/comprehensive.mustache
+                    , bench-data/escaped-var.mustache
+                    , bench-data/inverted-section.mustache
+                    , bench-data/lorem-ipsum.mustache
+                    , bench-data/nested-sections.mustache
+                    , bench-data/partial.mustache
+                    , bench-data/section.mustache
+                    , bench-data/unescaped-var-spec.mustache
+                    , bench-data/unescaped-var.mustache
                     , specs/comments.yml
                     , specs/delimiters.yml
                     , specs/interpolation.yml
                     , specs/inverted.yml
                     , specs/partials.yml
                     , specs/sections.yml
-                    , templates/foo.mustache
                     , templates/bar.mustache
+                    , templates/foo.mustache
 
 source-repository head
   type:               git
@@ -68,6 +77,7 @@
                     , base             >= 4.7  && < 5.0
                     , bytestring       >= 0.10 && < 0.11
                     , containers       >= 0.5  && < 0.6
+                    , deepseq          >= 1.4  && < 1.5
                     , directory        >= 1.2  && < 1.3
                     , exceptions       >= 0.8  && < 0.9
                     , filepath         >= 1.2  && < 1.5
@@ -101,7 +111,7 @@
                     , hspec            >= 2.0  && < 3.0
                     , hspec-megaparsec >= 0.2  && < 0.3
                     , megaparsec       >= 5.0  && < 6.0
-                    , stache           >= 0.1.0
+                    , stache           >= 0.1.1
                     , text             >= 1.2  && < 1.3
   other-modules:      Text.Mustache.Compile.THSpec
                     , Text.Mustache.ParserSpec
@@ -126,9 +136,26 @@
                     , file-embed
                     , hspec            >= 2.0  && < 3.0
                     , megaparsec       >= 5.0  && < 6.0
-                    , stache           >= 0.1.0
+                    , stache           >= 0.1.1
                     , text             >= 1.2  && < 1.3
                     , yaml             >= 0.8  && < 0.9
+  if flag(dev)
+    ghc-options:      -Wall -Werror
+  else
+    ghc-options:      -O2 -Wall
+  default-language:   Haskell2010
+
+benchmark bench
+  main-is:            Main.hs
+  hs-source-dirs:     bench
+  type:               exitcode-stdio-1.0
+  build-depends:      aeson            >= 0.11 && < 0.12
+                    , base             >= 4.7 && < 5.0
+                    , criterion        >= 0.6.2.1 && < 1.2
+                    , deepseq          >= 1.4  && < 1.5
+                    , megaparsec       >= 5.0  && < 6.0
+                    , stache           >= 0.1.1
+                    , text             >= 1.2  && < 1.3
   if flag(dev)
     ghc-options:      -Wall -Werror
   else
