diff --git a/Data/Aeson/Encode.hs b/Data/Aeson/Encode.hs
--- a/Data/Aeson/Encode.hs
+++ b/Data/Aeson/Encode.hs
@@ -17,13 +17,15 @@
     , encode
     ) where
 
-import Blaze.ByteString.Builder
-import Blaze.ByteString.Builder.Char.Utf8
-import Data.Attoparsec.Number (Number(..))
+import Blaze.ByteString.Builder (Builder, fromByteString, toLazyByteString)
+import Blaze.Text (double, integral)
 import Data.Aeson.Types (ToJSON(..), Value(..))
+import Data.Attoparsec.Number (Number(..))
 import Data.Monoid (mappend)
+import Data.Text.Encoding (encodeUtf8)
 import Numeric (showHex)
-import Blaze.Text (double, integral)
+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
+import qualified Blaze.ByteString.Builder.Char8 as Char8
 import qualified Data.ByteString.Lazy.Char8 as L
 import qualified Data.HashMap.Strict as H
 import qualified Data.Text as T
@@ -31,27 +33,29 @@
 
 -- | Encode a JSON value to a 'Builder'.
 fromValue :: Value -> Builder
-fromValue Null = fromByteString "null"
-fromValue (Bool b) = fromByteString $ if b then "true" else "false"
-fromValue (Number n) = fromNumber n
-fromValue (String s) = string s
+fromValue Null = {-# SCC "fromValue/Null" #-} fromByteString "null"
+fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}
+                     if b then fromByteString "true"
+                     else fromByteString "false"
+fromValue (Number n) = {-# SCC "fromValue/Number" #-} fromNumber n
+fromValue (String s) = {-# SCC "fromValue/String" #-} string s
 fromValue (Array v)
-    | V.null v = fromByteString "[]"
-    | otherwise = fromChar '[' `mappend`
+    | V.null v = {-# SCC "fromValue/Array" #-} fromByteString "[]"
+    | otherwise = {-# SCC "fromValue/Array" #-}
+                  Char8.fromChar '[' `mappend`
                   fromValue (V.unsafeHead v) `mappend`
-                  V.foldr f (fromChar ']') (V.unsafeTail v)
-  where f a z = fromChar ',' `mappend` fromValue a `mappend` z
-fromValue (Object m) =
+                  V.foldr f (Char8.fromChar ']') (V.unsafeTail v)
+  where f a z = Char8.fromChar ',' `mappend` fromValue a `mappend` z
+fromValue (Object m) = {-# SCC "fromValue/Object" #-}
     case H.toList m of
-      (x:xs) -> fromChar '{' `mappend`
-                one x `mappend`
-                foldr f (fromChar '}') xs
-      _ -> fromByteString "{}"
-  where f a z     = fromChar ',' `mappend` one a `mappend` z
-        one (k,v) = string k `mappend` fromChar ':' `mappend` fromValue v
+      (x:xs) -> Char8.fromChar '{' `mappend`
+                one x `mappend` foldr f (Char8.fromChar '}') xs
+      _      -> fromByteString "{}"
+  where f a z     = Char8.fromChar ',' `mappend` one a `mappend` z
+        one (k,v) = string k `mappend` Char8.fromChar ':' `mappend` fromValue v
 
 string :: T.Text -> Builder
-string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
+string s = Char8.fromChar '"' `mappend` (quote s) `mappend` Char8.fromChar '"'
   where
     quote q = case T.uncons t of
                 Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
@@ -64,10 +68,15 @@
     escape '\r' = fromByteString "\\r"
     escape '\t' = fromByteString "\\t"
     escape c
-        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
-        | otherwise  = fromChar c
+        | c < '\x20' = Char8.fromString $
+                       "\\u" ++ replicate (4 - length h) '0' ++ h
+        | otherwise  = Utf8.fromChar c
         where h = showHex (fromEnum c) ""
 
+-- The version in blaze-builder is way slower.
+fromText :: T.Text -> Builder
+fromText t = fromByteString (encodeUtf8 t)
+
 fromNumber :: Number -> Builder
 fromNumber (I i) = integral i
 fromNumber (D d)
@@ -76,5 +85,6 @@
 
 -- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
 encode :: ToJSON a => a -> L.ByteString
-encode = toLazyByteString . fromValue . toJSON
+encode = {-# SCC "encode" #-} toLazyByteString . fromValue .
+         {-# SCC "toJSON" #-} toJSON
 {-# INLINE encode #-}
diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,5 +1,5 @@
 name:            aeson
-version:         0.4.0.0
+version:         0.4.0.1
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Web, JSON
@@ -84,6 +84,7 @@
 
 extra-source-files:
     README.markdown
+    benchmarks/*.cabal
     benchmarks/*.hs
     benchmarks/*.py
     benchmarks/Makefile
@@ -139,7 +140,7 @@
     ghc-options: -Werror
     ghc-prof-options: -auto-all
 
-  ghc-options:      -Wall
+  ghc-options: -O2 -Wall
 
 test-suite tests
   type:           exitcode-stdio-1.0
diff --git a/benchmarks/AesonEncode.hs b/benchmarks/AesonEncode.hs
--- a/benchmarks/AesonEncode.hs
+++ b/benchmarks/AesonEncode.hs
@@ -3,8 +3,6 @@
 import Control.Exception
 import Control.Monad
 import Data.Aeson
-import Data.Aeson.Encode
-import Data.Aeson.Parser
 import Data.Attoparsec
 import Data.Time.Clock
 import System.Environment (getArgs)
diff --git a/benchmarks/AesonParse.hs b/benchmarks/AesonParse.hs
--- a/benchmarks/AesonParse.hs
+++ b/benchmarks/AesonParse.hs
@@ -1,10 +1,8 @@
 {-# LANGUAGE BangPatterns, OverloadedStrings #-}
 
-import Control.DeepSeq
 import Control.Exception
 import Control.Monad
 import Data.Aeson
-import Data.Aeson.Parser
 import Data.Attoparsec
 import Data.Time.Clock
 import System.Environment (getArgs)
diff --git a/benchmarks/CompareWithJSON.hs b/benchmarks/CompareWithJSON.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/CompareWithJSON.hs
@@ -0,0 +1,70 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+import Blaze.ByteString.Builder (toLazyByteString)
+import Blaze.ByteString.Builder.Char.Utf8 (fromString)
+import Control.DeepSeq (NFData(rnf))
+import Criterion.Main
+import qualified Data.Aeson as A
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Internal as BL
+import qualified Text.JSON as J
+
+instance (NFData v) => NFData (J.JSObject v) where
+  rnf o = rnf (J.fromJSObject o)
+
+instance NFData J.JSValue where
+  rnf J.JSNull = ()
+  rnf (J.JSBool b) = rnf b
+  rnf (J.JSRational a b) = rnf a `seq` rnf b `seq` ()
+  rnf (J.JSString s) = rnf (J.fromJSString s)
+  rnf (J.JSArray lst) = rnf lst
+  rnf (J.JSObject o) = rnf o
+
+instance NFData BL.ByteString where
+  rnf (BL.Chunk _ bs) = rnf bs
+  rnf BL.Empty        = ()
+
+decodeJ :: String -> J.JSValue
+decodeJ s =
+  case J.decodeStrict s of
+    J.Ok v -> v
+    J.Error _ -> error "fail to parse via JSON"
+
+decodeA :: BL.ByteString -> A.Value
+decodeA s = case A.decode s of
+              Just v -> v
+              Nothing -> error "fail to parse via Aeson"
+
+encodeJ :: J.JSValue -> BL.ByteString
+encodeJ = toLazyByteString . fromString . J.encode
+
+main :: IO ()
+main = do
+  let enFile = "json-data/twitter100.json"
+      jpFile = "json-data/jp100.json"
+  enA <- BL.readFile enFile
+  enJ <- readFile enFile
+  jpA <- BL.readFile jpFile
+  jpJ <- readFile jpFile
+  defaultMain [
+      bgroup "decode" [
+        bgroup "en" [
+          bench "aeson" $ nf decodeA enA
+        , bench "json"  $ nf decodeJ enJ
+        ]
+      , bgroup "jp" [
+          bench "aeson" $ nf decodeA jpA
+        , bench "json"  $ nf decodeJ jpJ
+        ]
+      ]
+    , bgroup "encode" [
+        bgroup "en" [
+          bench "aeson" $ nf A.encode (decodeA enA)
+        , bench "json"  $ nf encodeJ (decodeJ enJ)
+        ]
+      , bgroup "jp" [
+          bench "aeson" $ nf A.encode (decodeA jpA)
+        , bench "json"  $ nf encodeJ (decodeJ jpJ)
+        ]
+      ]
+    ]
diff --git a/benchmarks/JsonParse.hs b/benchmarks/JsonParse.hs
--- a/benchmarks/JsonParse.hs
+++ b/benchmarks/JsonParse.hs
@@ -1,13 +1,12 @@
 {-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 import Control.DeepSeq
-import Control.Exception
 import Control.Monad
 import Text.JSON
 import Data.Time.Clock
 import System.Environment (getArgs)
 import System.IO
-import qualified Data.ByteString as B
 
 instance NFData JSValue where
     rnf JSNull = ()
diff --git a/benchmarks/aeson-benchmarks.cabal b/benchmarks/aeson-benchmarks.cabal
new file mode 100644
--- /dev/null
+++ b/benchmarks/aeson-benchmarks.cabal
@@ -0,0 +1,40 @@
+name:                aeson-benchmarks
+version:             0
+build-type:          Simple
+
+cabal-version:       >=1.2
+
+executable aeson-benchmark-compare-with-json
+  main-is: CompareWithJSON.hs
+  ghc-options: -Wall -O2
+  build-depends:
+    aeson == 0.4.0.0,
+    base,
+    blaze-builder,
+    bytestring,
+    criterion,
+    json
+
+executable aeson-benchmark-aeson-encode
+  main-is: AesonEncode.hs
+  ghc-options: -Wall -O2
+  build-depends:
+    aeson == 0.4.0.0,
+    base
+
+executable aeson-benchmark-aeson-parse
+  main-is: AesonParse.hs
+  ghc-options: -Wall -O2
+  build-depends:
+    aeson == 0.4.0.0,
+    attoparsec,
+    base
+
+executable aeson-benchmark-json-parse
+  main-is: JsonParse.hs
+  ghc-options: -Wall -O2
+  build-depends:
+    base,
+    deepseq,
+    json,
+    time
