diff --git a/Data/Text/Buildable.hs b/Data/Text/Buildable.hs
--- a/Data/Text/Buildable.hs
+++ b/Data/Text/Buildable.hs
@@ -28,7 +28,7 @@
 import Data.Time.LocalTime (LocalTime, TimeOfDay, TimeZone, ZonedTime)
 import Data.Word (Word, Word8, Word16, Word32, Word64)
 import Foreign.Ptr (IntPtr, WordPtr, Ptr, ptrToWordPtr)
-import qualified Data.Double.Conversion as C
+import qualified Data.Double.Conversion.Text as C
 import qualified Data.Text as ST
 import qualified Data.Text.Lazy as LT
 
@@ -108,11 +108,11 @@
     build a = build (numerator a) <> singleton '/' <> build (denominator a)
 
 instance Buildable Float where
-    build = fromText . C.toShortest . realToFrac
+    build = fromText . C.toPrecision 6 . realToFrac
     {-# INLINE build #-}
 
 instance Buildable Double where
-    build = fromText . C.toShortest
+    build = fromText . C.toPrecision 6
     {-# INLINE build #-}
 
 instance Buildable DiffTime where
diff --git a/Data/Text/Format.hs b/Data/Text/Format.hs
--- a/Data/Text/Format.hs
+++ b/Data/Text/Format.hs
@@ -42,36 +42,52 @@
 import Data.Text.Lazy.Builder
 import Prelude hiding (exp, print)
 import System.IO (Handle)
-import qualified Data.Double.Conversion as C
+import qualified Data.Double.Conversion.Text as C
 import qualified Data.Text as ST
 import qualified Data.Text.Buildable as B
 import qualified Data.Text.Lazy as LT
 import qualified Data.Text.Lazy.IO as LT
 
+-- Format strings are almost always constants, and they're expensive
+-- to interpret (which we refer to as "cracking" here).  We'd really
+-- like to have GHC memoize the cracking of a known-constant format
+-- string, so that it occurs at most once.
+--
+-- To achieve this, we arrange to have the cracked version of a format
+-- string let-floated out as a CAF, by inlining the definitions of
+-- build and functions that invoke it.  This works well with GHC 7.
+
 -- | Render a format string and arguments to a 'Builder'.
 build :: Params ps => Format -> ps -> Builder
-build (Format fmt) ps = zipParams (map fromText . ST.splitOn "{}" $ fmt) xs
-  where zipParams (f:fs) (y:ys) = f <> y <> zipParams fs ys
-        zipParams [f] []        = f
-        zipParams _ _ = error . LT.unpack $ format
-                        "Data.Text.Format.build: {} sites, but {} parameters"
-                        (ST.count "{}" fmt, length xs)
-        xs = buildParams ps
+build fmt ps = zipParams fmt (crack fmt) (buildParams ps)
+{-# INLINE build #-}
 
+zipParams :: Format -> [Builder] -> [Builder] -> Builder
+zipParams fmt xs = go xs
+  where go (f:fs) (y:ys) = f <> y <> go fs ys
+        go [f] []        = f
+        go _ _ = error . LT.unpack $ format
+                 "Data.Text.Format.build: {} sites, but {} parameters"
+                 (ST.count "{}" (fromFormat fmt), length xs)
+
+crack :: Format -> [Builder]
+crack = map fromText . ST.splitOn "{}" . fromFormat
+
 -- | Render a format string and arguments to a 'LT.Text'.
 format :: Params ps => Format -> ps -> LT.Text
 format fmt ps = toLazyText $ build fmt ps
+{-# INLINE format #-}
 
 -- | Render a format string and arguments, then print the result.
 print :: (MonadIO m, Params ps) => Format -> ps -> m ()
-{-# SPECIALIZE print :: (Params ps) => Format -> ps -> IO () #-}
 print fmt ps = liftIO . LT.putStr . toLazyText $ build fmt ps
+{-# INLINE print #-}
 
 -- | Render a format string and arguments, then print the result to
 -- the given file handle.
 hprint :: (MonadIO m, Params ps) => Handle -> Format -> ps -> m ()
-{-# SPECIALIZE hprint :: (Params ps) => Handle -> Format -> ps -> IO () #-}
 hprint h fmt ps = liftIO . LT.hPutStr h . toLazyText $ build fmt ps
+{-# INLINE hprint #-}
 
 -- | Pad the left hand side of a string until it reaches @k@
 -- characters wide, if necessary filling with character @c@.
@@ -120,3 +136,4 @@
 -- is added.)
 hex :: Integral a => a -> Builder
 hex = B.build . Hex
+{-# INLINE hex #-}
diff --git a/Data/Text/Format/Types/Internal.hs b/Data/Text/Format/Types/Internal.hs
--- a/Data/Text/Format/Types/Internal.hs
+++ b/Data/Text/Format/Types/Internal.hs
@@ -43,8 +43,8 @@
 --
 -- The underlying type is 'Text', so literal Haskell strings that
 -- contain Unicode characters will be correctly handled.
-newtype Format = Format Text
-    deriving (Eq, Ord, Typeable)
+newtype Format = Format { fromFormat :: Text }
+    deriving (Eq, Ord, Typeable, Show)
 
 instance Monoid Format where
     Format a `mappend` Format b = Format (a `mappend` b)
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
--- a/benchmarks/Benchmarks.hs
+++ b/benchmarks/Benchmarks.hs
@@ -26,8 +26,10 @@
        , bgroup "comparison" [
            bench "format1" $ nf (format "hi mom {}\n") (Only (pi::Double))
          , bench "printf1" $ nf (printf1 "hi mom %f\n") (pi::Double)
+         , bench "show1" $ nf (\d -> "hi mom " ++ show d ++ "\n") (pi::Double)
          , bench "format2" $ nf (format "hi mom {} {}\n") (pi::Double, "yeah"::T.Text)
          , bench "printf2" $ nf (printf2 "hi mom %f %s\n") (pi::Double, "yeah"::String)
+         , bench "show2" $ nf (\(d,s) -> "hi mom " ++ show d ++ " " ++ show s ++ "\n") (pi::Double, "yeah"::String)
          ]
        , bgroup "types" [
            bench "unit" $ nf (format "hi") ()
diff --git a/benchmarks/Simple.hs b/benchmarks/Simple.hs
--- a/benchmarks/Simple.hs
+++ b/benchmarks/Simple.hs
@@ -3,6 +3,7 @@
 --module Main (main) where
 
 import Control.Monad
+import Data.Char
 import Data.Bits
 import System.Environment
 import Data.Text.Format as T
@@ -41,28 +42,32 @@
   L.putStr . encodeUtf8 $ t
 
 arg :: Int -> Text
-arg i = T.replicate (i.&.4) "fnord"
+arg i = "fnord" `T.append` (T.take (i `mod` 6) "foobar")
 {-# NOINLINE arg #-}
 
 one count = counting count $ \i x -> do
-  let t = T.format "hi mom {}\n" (Only (arg i))
+  let k = arg i
+  let t = {-# SCC "one/format" #-} T.format "hi mom {}\n" (Only k)
   L.putStr . encodeUtf8 $ t
 
 two count = counting count $ \i x -> do
-  let t = T.format "hi mom {} {}\n" (arg i,arg (i+1))
+  let k = arg i
+  let t = {-# SCC "two/format" #-} T.format "hi mom {} {}\n" (k,k)
   L.putStr . encodeUtf8 $ t
 
 three count = counting count $ \i x -> do
-  let t = T.format "hi mom {} {} {}\n" (arg i,arg (i+1),arg (i+2))
+  let k = arg i
+  let t = {-# SCC "three/format" #-} T.format "hi mom {} {} {}\n" (k,k,k)
   L.putStr . encodeUtf8 $ t
 
 four count = counting count $ \i x -> do
-  let t = T.format "hi mom {} {} {} {}\n" (arg i,arg (i+1),arg (i+2),arg (i+3))
+  let k = arg i
+  let t = {-# SCC "four/format" #-} T.format "hi mom {} {} {} {}\n" (k,k,k,k)
   L.putStr . encodeUtf8 $ t
 
 five count = counting count $ \i x -> do
-  let t = T.format "hi mom {} {} {} {} {}\n"
-          (arg i,arg (i+1),arg (i+2),arg (i+3),arg (i+4))
+  let k = arg i
+  let t = {-# SCC "five/format" #-} T.format "hi mom {} {} {} {} {}\n" (k,k,k,k,k)
   L.putStr . encodeUtf8 $ t
 
 dpi :: Double
diff --git a/text-format.cabal b/text-format.cabal
--- a/text-format.cabal
+++ b/text-format.cabal
@@ -1,5 +1,5 @@
 name:           text-format
-version:        0.3.0.0
+version:        0.3.0.2
 license:        BSD3
 license-file:   LICENSE
 homepage:       https://github.com/mailrank/text-format
@@ -13,7 +13,7 @@
 cabal-version:  >= 1.8
 build-type:     Simple
 description:
-    A text formatting library optimized for ease of use and high
+    A text formatting library optimized for both ease of use and high
     performance.
 
 extra-source-files:
@@ -41,7 +41,7 @@
   build-depends:
     array,
     base == 4.*,
-    double-conversion,
+    double-conversion >= 0.2.0.0,
     ghc-prim,
     integer-gmp,
     old-locale,
