diff --git a/Data/ByteString/Base64.hs b/Data/ByteString/Base64.hs
--- a/Data/ByteString/Base64.hs
+++ b/Data/ByteString/Base64.hs
@@ -28,29 +28,29 @@
 -- | Encode a string into base64 form.  The result will always be a
 -- multiple of 4 bytes in length.
 encode :: ByteString -> ByteString
-encode = encodeWithAlphabet alphabet
+encode s = encodeWith (mkEncodeTable alphabet) s
 
 -- | Decode a base64-encoded string.  This function strictly follows
 -- the specification in RFC 4648,
 -- <http://www.apps.ietf.org/rfc/rfc4648.html>.
 decode :: ByteString -> Either String ByteString
-decode = decodeWithTable decodeFP
+decode s = decodeWithTable decodeFP s
 
 -- | Decode a base64-encoded string.  This function is lenient in
 -- following the specification from RFC 4648,
 -- <http://www.apps.ietf.org/rfc/rfc4648.html>, and will not generate
 -- parse errors no matter how poor its input.
 decodeLenient :: ByteString -> ByteString
-decodeLenient = decodeLenientWithTable decodeFP
-
+decodeLenient s = decodeLenientWithTable decodeFP s
 
 alphabet :: ByteString
 alphabet = B.pack $ [65..90] ++ [97..122] ++ [48..57] ++ [43,47]
 {-# NOINLINE alphabet #-}
 
 decodeFP :: ForeignPtr Word8
-PS decodeFP _ _ = B.pack $ replicate 43 x ++ [62,x,x,x,63] ++ [52..61] ++ [x,x,
-  x,done,x,x,x] ++ [0..25] ++ [x,x,x,x,x,x] ++ [26..51] ++ replicate 133 x
+PS decodeFP _ _ = B.pack $
+  replicate 43 x ++ [62,x,x,x,63] ++ [52..61] ++ [x,x,x,done,x,x,x] ++
+  [0..25] ++ [x,x,x,x,x,x] ++ [26..51] ++ replicate 133 x
 {-# NOINLINE decodeFP #-}
 
 x :: Integral a => a
diff --git a/Data/ByteString/Base64/Internal.hs b/Data/ByteString/Base64/Internal.hs
--- a/Data/ByteString/Base64/Internal.hs
+++ b/Data/ByteString/Base64/Internal.hs
@@ -13,9 +13,10 @@
 
 module Data.ByteString.Base64.Internal
     (
-      encodeWithAlphabet
+      encodeWith
     , decodeWithTable
     , decodeLenientWithTable
+    , mkEncodeTable
     , joinWith
     , done
     , peek8, poke8, peek8_32
@@ -40,11 +41,10 @@
 peek8_32 :: Ptr Word8 -> IO Word32
 peek8_32 = fmap fromIntegral . peek8
 
--- | Encode a string into base64 form.  The result will always be a
--- multiple of 4 bytes in length. This function takes the encoding
--- alphabet (for @base64@ or @base64url@) as the first paramert.
-encodeWithAlphabet :: ByteString -> ByteString -> ByteString
-encodeWithAlphabet alphabet@(PS alfaFP _ _) (PS sfp soff slen)
+-- | Encode a string into base64 form.  The result will always be a multiple
+-- of 4 bytes in length.
+encodeWith :: EncodeTable -> ByteString -> ByteString
+encodeWith (ET alfaFP encodeTable) (PS sfp soff slen)
     | slen > maxBound `div` 4 =
         error "Data.ByteString.Base64.encode: input too long"
     | otherwise = unsafePerformIO $ do
@@ -88,17 +88,20 @@
         withForeignPtr dfp $ \dptr ->
           fill (castPtr dptr) (sptr `plusPtr` soff)
   return $! PS dfp 0 dlen
-  where -- The encoding table is constructed such that the expansion of a 12bit block
-        -- to a 16bit block can be done by a single Word16 copy from the correspoding
-        -- table entry to the target address. The 16bit blocks are stored in big-endian
-        -- order, as the indices into the table are built in big-endian order.
-        encodeTable :: ForeignPtr Word16
-        encodeTable = 
-            case table of PS fp _ _ -> castForeignPtr fp
-          where
-            ix    = fromIntegral . B.index alphabet
-            table = B.pack $ concat $ [ [ix j, ix k] | j <- [0..63], k <- [0..63] ]
-        {-# NOINLINE encodeTable #-}
+
+data EncodeTable = ET (ForeignPtr Word8) (ForeignPtr Word16)
+
+-- The encoding table is constructed such that the expansion of a 12-bit
+-- block to a 16-bit block can be done by a single Word16 copy from the
+-- correspoding table entry to the target address. The 16-bit blocks are
+-- stored in big-endian order, as the indices into the table are built in
+-- big-endian order.
+mkEncodeTable :: ByteString -> EncodeTable
+mkEncodeTable alphabet@(PS afp _ _) =
+    case table of PS fp _ _ -> ET afp (castForeignPtr fp)
+  where
+    ix    = fromIntegral . B.index alphabet
+    table = B.pack $ concat $ [ [ix j, ix k] | j <- [0..63], k <- [0..63] ]
 
 -- | Efficiently intersperse a terminator string into another at
 -- regular intervals, and terminate the input with it.
diff --git a/Data/ByteString/Base64/URL.hs b/Data/ByteString/Base64/URL.hs
--- a/Data/ByteString/Base64/URL.hs
+++ b/Data/ByteString/Base64/URL.hs
@@ -28,7 +28,7 @@
 -- | Encode a string into base64url form.  The result will always be a
 -- multiple of 4 bytes in length.
 encode :: ByteString -> ByteString
-encode = encodeWithAlphabet alphabet
+encode = encodeWith (mkEncodeTable alphabet)
 
 -- | Decode a base64url-encoded string.  This function strictly follows
 -- the specification in RFC 4648,
diff --git a/base64-bytestring.cabal b/base64-bytestring.cabal
--- a/base64-bytestring.cabal
+++ b/base64-bytestring.cabal
@@ -1,5 +1,5 @@
 name:                base64-bytestring
-version:             0.1.1.0
+version:             0.1.1.1
 synopsis:            Fast base64 encoding and deconding for ByteStrings
 description:         Fast base64 encoding and deconding for ByteStrings
 homepage:            https://github.com/bos/base64-bytestring
@@ -15,6 +15,7 @@
 
 extra-source-files:
   README.markdown
+  benchmarks/BM.hs
   tests/Transcode.hs
   tests/transcode.py
 
diff --git a/benchmarks/BM.hs b/benchmarks/BM.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/BM.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import Criterion.Main
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Base64 as B
+import qualified Data.ByteString.Base64 as U
+
+sized name orig =
+    bgroup name [
+      bgroup "normal" [
+        bench "decode" $ whnf B.decode enc
+      , bench "decodeLenient" $ whnf B.decodeLenient enc
+      , bench "encode" $ whnf B.encode orig
+      ]
+    , bgroup "url" [
+        bench "decode" $ whnf U.decode enc
+      , bench "decodeLenient" $ whnf U.decodeLenient enc
+      , bench "encode" $ whnf U.encode orig
+      ]
+    ]
+  where enc = U.encode orig
+
+main :: IO ()
+main = defaultMain [
+         sized "small" input
+       , sized "medium" (B.concat (replicate 100 input))
+       , sized "large" (B.concat (replicate 10000 input))
+       ]
+  where input = "abcdABCD0123[];'"
