diff --git a/Data/FileStore/Git.hs b/Data/FileStore/Git.hs
--- a/Data/FileStore/Git.hs
+++ b/Data/FileStore/Git.hs
@@ -234,7 +234,7 @@
 -}
 
 gitLogFormat :: String
-gitLogFormat = "%H%n%ct%n%an%n%ae%n%s%n%x00"
+gitLogFormat = "%H%n%ct%n%an%n%ae%n%B%n%x00"
 
 -- | Return list of log entries for the given time frame and list of resources.
 -- If list of resources is empty, log entries for all resources are returned.
diff --git a/Data/FileStore/Mercurial.hs b/Data/FileStore/Mercurial.hs
--- a/Data/FileStore/Mercurial.hs
+++ b/Data/FileStore/Mercurial.hs
@@ -19,7 +19,8 @@
 import Data.FileStore.Types
 import Data.Maybe (fromJust)
 import System.Exit
-import Data.FileStore.Utils (withSanityCheck, hashsMatch, runShellCommand, withVerifyDir, grepSearchRepo) 
+import Data.FileStore.Utils (withSanityCheck, hashsMatch, withVerifyDir, grepSearchRepo)
+import Data.FileStore.MercurialCommandServer
 import Data.ByteString.Lazy.UTF8 (toString)
 import qualified Data.ByteString.Lazy as B
 import qualified Text.ParserCombinators.Parsec as P
@@ -50,20 +51,13 @@
   , idsMatch          = const hashsMatch repo
   }
 
--- | Run a mercurial command and return error status, error output, standard output.  The repository
--- is used as working directory.
-runMercurialCommand :: FilePath -> String -> [String] -> IO (ExitCode, String, B.ByteString)
-runMercurialCommand repo command args = do
-  (status, err, out) <- runShellCommand repo Nothing "hg" (command : args)
-  return (status, toString err, out)
-
 -- | Initialize a repository, creating the directory if needed.
 mercurialInit :: FilePath -> IO ()
 mercurialInit repo = do
   exists <- doesDirectoryExist repo
   when exists $ withVerifyDir repo $ throwIO RepositoryExists
   createDirectoryIfMissing True repo
-  (status, err, _) <- runMercurialCommand repo "init" []
+  (status, err, _) <- rawRunMercurialCommand repo "init" []
   if status == ExitSuccess
      then
        -- Add a hook so that changes made remotely via hg will be reflected in
diff --git a/Data/FileStore/MercurialCommandServer.hs b/Data/FileStore/MercurialCommandServer.hs
new file mode 100644
--- /dev/null
+++ b/Data/FileStore/MercurialCommandServer.hs
@@ -0,0 +1,234 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{- |
+   Module      : Data.FileStore.MercurialCommandServer
+   Copyright   : Copyright (C) 2011 John Lenz (lenz@math.uic.edu)
+   License     : BSD 3
+
+   Maintainer  : John MacFarlane <jgm@berkeley.edu>
+   Stability   : alpha
+   Portability : GHC 6.10 required
+
+   In version 1.9, mercurial introduced a command server which allows
+   a single instance of mercurial to be launched and multiple commands
+   can be executed without requiring mercurial to start and stop.  See
+   http://mercurial.selenic.com/wiki/CommandServer
+-}
+
+module Data.FileStore.MercurialCommandServer
+    ( runMercurialCommand
+    , rawRunMercurialCommand
+    )
+where
+
+import Control.Applicative ((<$>))
+import Control.Exception (Exception, onException, throwIO)
+import Control.Monad (when)
+import Data.Bits (shiftL, shiftR, (.|.))
+import Data.Char (isLower, isUpper)
+import Data.FileStore.Utils (runShellCommand)
+import Data.IORef (IORef, newIORef, readIORef, atomicModifyIORef)
+import Data.List (intercalate, isPrefixOf)
+import Data.List.Split (splitOn)
+import Data.Typeable (Typeable)
+import Data.Word (Word32)
+import System.Exit (ExitCode(..))
+import System.IO (Handle, hClose, hPutStr, hFlush)
+import System.IO.Unsafe (unsafePerformIO)
+import System.Process (runInteractiveProcess)
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.UTF8 as UTF8
+import qualified Data.ByteString.Char8 as B8
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.UTF8 as LUTF8
+import qualified Data.Map as M
+
+-- | Maximum number of servers to keep around
+maxPoolSize :: Int
+maxPoolSize = 2
+
+-- | Run a mercurial command and return error status, error output, standard output.  The repository
+-- is used as working directory.
+runMercurialCommand :: FilePath -> String -> [String] -> IO (ExitCode, String, BL.ByteString)
+runMercurialCommand repo command args = do
+  server <- getServer repo
+  case server of
+     Nothing -> rawRunMercurialCommand repo command args
+     Just h  -> do ret <- runMercurialServer command args h `onException` cleanupServer h
+                   putServer repo h
+                   return ret
+
+-- | Run a mercurial command directly without using the server.
+rawRunMercurialCommand :: FilePath -> String -> [String] -> IO (ExitCode, String, BL.ByteString)
+rawRunMercurialCommand repo command args = do
+   (status, err, out) <- runShellCommand repo Nothing "hg" (command : args)
+   return (status, LUTF8.toString err, out)
+
+-- | Create a new command server for the given repository
+createServer :: FilePath -> IO (Handle,Handle,Handle)
+createServer repo = do
+    (hin,hout,herr,_) <- runInteractiveProcess "hg" ["serve", "--cmdserver", "pipe"] (Just repo) Nothing
+    hello <- readMessage hout
+    case hello of
+       MessageO _ -> return (hin,hout,herr)
+       MessageE x -> throwIO $ MercurialServerException (UTF8.toString x)
+       _          -> throwIO $ MercurialServerException "unknown hello message"
+
+-- | Cleanup a command sever.  Mercurial will automatically exit itself
+--   when the handles are closed.
+cleanupServer :: (Handle,Handle,Handle) -> IO ()
+cleanupServer (hin,hout,herr) = hClose hin >> hClose hout >> hClose herr
+
+-- | format a command for sending to the server
+formatCommand :: String -> [String] -> B.ByteString
+formatCommand cmd args = UTF8.fromString $ intercalate "\0" $ cmd : args
+
+-- | run a command using the mercurial server
+runMercurialServer :: String -> [String] -> (Handle,Handle,Handle) -> IO (ExitCode, String, BL.ByteString)
+runMercurialServer cmd args (hin,hout,herr) = do
+    hPutStr hin "runcommand\n"
+    let fcmd = formatCommand cmd args
+    hWriteWord32be hin $ fromIntegral $ B.length fcmd
+    B.hPut hin fcmd
+    hFlush hin
+    processUntilR hout herr
+
+-- | Read messages from the server until the command finishes or an error message appears
+processUntilR :: Handle -> Handle -> IO (ExitCode, String, BL.ByteString)
+processUntilR hout _ = loop BL.empty BL.empty
+  where loop out err =
+          do m <- readMessage hout
+             case m of
+                MessageO x -> loop (BL.append out $ BL.fromChunks [x]) err
+                MessageE x -> loop out (BL.append err $ BL.fromChunks [x])
+                MessageR c -> if c == 0
+                                then return (ExitSuccess, "", out)
+                                else return (ExitFailure c, LUTF8.toString err, out)
+
+data MercurialMessage = MessageO B.ByteString
+                      | MessageE B.ByteString
+                      | MessageR Int
+
+data MercurialServerException = MercurialServerException String
+  deriving (Show,Typeable)
+instance Exception MercurialServerException
+
+-- | Read a single message
+readMessage :: Handle -> IO MercurialMessage
+readMessage hout = do
+    buf <- B.hGet hout 1
+    when (buf == B.empty) $
+       throwIO $ MercurialServerException "Unknown channel"
+    let c = B8.head buf
+    -- Mercurial says unknown lower case channels can be ignored, but upper case channels
+    -- must be handled.  Currently there are two upper case channels, 'I' and 'L' which
+    -- are both used for user input/output.  So error on any upper case channel.
+    when (isUpper c) $
+       throwIO $ MercurialServerException $ "Unknown channel " ++ show c
+    len <- hReadWord32be hout
+    bdata <- B.hGet hout len
+    when (B.length bdata /= len) $
+       throwIO $ MercurialServerException "Mercurial did not produce enough output"
+    case c of
+      'r' | len >= 4 -> return $ MessageR $ bsReadWord32be bdata
+      'r'            -> throwIO $ MercurialServerException $ "return value is fewer than 4 bytes"
+      'o'            -> return $ MessageO bdata
+      'e'            -> return $ MessageE bdata
+      _ | isLower c  -> readMessage hout -- skip this message
+      _              -> throwIO $ MercurialServerException $ "Unknown channel " ++ show c
+
+-- | Read a 32-bit big-endian into an Int
+hReadWord32be :: Handle -> IO Int
+hReadWord32be h = do
+    s <- B.hGet h 4
+    when (B.length s /= 4) $
+    	throwIO $ MercurialServerException "unable to read int"
+    return $ bsReadWord32be s
+
+-- | Read a 32-bit big-endian from a bytestring into an Int
+bsReadWord32be :: B.ByteString -> Int
+bsReadWord32be s = (fromIntegral (s `B.index` 0) `shiftL` 24) .|.
+                   (fromIntegral (s `B.index` 1) `shiftL` 16) .|.
+                   (fromIntegral (s `B.index` 2) `shiftL`  8) .|.
+                   (fromIntegral (s `B.index` 3) )
+
+-- | Write a Word32 in big-endian to the handle
+hWriteWord32be :: Handle -> Word32 -> IO ()
+hWriteWord32be h w = B.hPut h buf
+  where buf = B.pack [  -- fromIntegeral to convert to Word8
+                fromIntegral (w `shiftR` 24),
+                fromIntegral (w `shiftR` 16),
+                fromIntegral (w `shiftR`  8),
+                fromIntegral w
+              ]
+
+-------------------------------------------------------------------
+-- Maintain a pool of mercurial servers.  Currently stored in a
+-- global IORef.  The code must provide two functions, to get
+-- and put a server from the pool.  The code above takes care of
+-- cleaning up if an exception occurs.
+-------------------------------------------------------------------
+
+data MercurialGlobalState = MercurialGlobalState {
+    useCommandServer :: Maybe Bool
+  , serverHandles    :: M.Map FilePath [(Handle,Handle,Handle)]
+} deriving (Show)
+
+-- | See http://www.haskell.org/haskellwiki/Top_level_mutable_state
+mercurialGlobalVar :: IORef MercurialGlobalState
+{-# NOINLINE mercurialGlobalVar #-}
+mercurialGlobalVar = unsafePerformIO (newIORef (MercurialGlobalState Nothing M.empty))
+
+-- | Pull a server out of the pool.  Returns nothing if the mercurial version
+--   does not support servers.
+getServer :: FilePath -> IO (Maybe (Handle, Handle, Handle))
+getServer repo = do
+    use <- useCommandServer <$> readIORef mercurialGlobalVar
+    case use of
+      Just False -> return Nothing
+      Nothing    -> do isok <- checkVersion
+                       atomicModifyIORef mercurialGlobalVar $ \state ->
+                          (state { useCommandServer = Just isok }, ())
+                       getServer repo
+      Just True  -> allocateServer repo
+
+-- | Helper function called once we know that mercurial supports servers
+allocateServer :: FilePath -> IO (Maybe (Handle, Handle, Handle))
+allocateServer repo = do
+    ret <- atomicModifyIORef mercurialGlobalVar $ \state ->
+             case M.lookup repo (serverHandles state) of
+                Just (x:xs) -> (state { serverHandles = M.insert repo xs (serverHandles state)}, Right x)
+                _           -> (state, Left ())
+    case ret of
+      Right x -> return $ Just x
+      Left () -> Just <$> createServer repo
+
+-- | Puts a server back in the pool if the pool is not full,
+--   otherwise closes the server.
+putServer :: FilePath -> (Handle,Handle,Handle) -> IO ()
+putServer repo h = do
+    ret <- atomicModifyIORef mercurialGlobalVar $ \state -> do
+              case M.lookup repo (serverHandles state) of
+                  Just xs | length xs >= maxPoolSize -> (state, Right ())
+                  Just xs -> (state { serverHandles = M.insert repo (h:xs) (serverHandles state)}, Left ())
+                  Nothing -> (state { serverHandles = M.insert repo [h] (serverHandles state)}, Left ())
+    case ret of
+      Right () -> cleanupServer h
+      Left  () -> return ()
+
+-- | Check if the mercurial version supports servers
+checkVersion :: IO Bool
+checkVersion = do
+    (status,_,out) <- runShellCommand "." Nothing "hg" ["version", "-q"]
+    case status of
+      ExitFailure _ -> return False
+      ExitSuccess   -> return $ parseVersion (LUTF8.toString out) >= [2,0]
+
+-- | hg version -q returns something like "Mercurial Distributed SCM (version 1.9.1)"
+--   This function returns the list [1,9,1]
+parseVersion :: String -> [Int]
+parseVersion b = if starts then verLst else [0]
+  where msg = "Mercurial Distributed SCM (version "
+        starts = isPrefixOf msg b
+        ver    = takeWhile (/= ')') $ drop (length msg) b
+        verLst = map read $ splitOn "." ver
diff --git a/filestore.cabal b/filestore.cabal
--- a/filestore.cabal
+++ b/filestore.cabal
@@ -1,5 +1,5 @@
 Name:                filestore
-Version:             0.4.0.4
+Version:             0.4.1
 Cabal-version:       >= 1.2
 Build-type:          Custom
 Tested-with:         GHC==6.10.1
@@ -33,12 +33,13 @@
 Library
     Build-depends:       base >= 4 && < 5,
                          bytestring >= 0.9 && < 1.0,
+                         containers >= 0.3 && < 0.5,
                          utf8-string >= 0.3 && < 0.4,
-                         filepath >= 1.1 && < 1.3,
+                         filepath >= 1.1 && < 1.4,
                          directory >= 1.0 && < 1.2,
                          parsec >= 2 && < 3.2,
                          process >= 1.0 && < 1.2,
-                         time >= 1.1 && < 1.3,
+                         time >= 1.1 && < 1.5,
                          xml >= 1.3 && < 1.4,
                          split >= 0.1 && < 0.2,
                          Diff >= 0.1.2 && < 0.2,
@@ -47,7 +48,10 @@
     Exposed-modules:     Data.FileStore, Data.FileStore.Types, Data.FileStore.Git, Data.FileStore.Darcs, Data.FileStore.Mercurial,
                          -- Data.FileStore.Sqlite3,
                          Data.FileStore.Utils, Data.FileStore.Generic
-    Other-modules:       Paths_filestore, Data.FileStore.DarcsXml
+    Other-modules:       Paths_filestore,
+                         Data.FileStore.DarcsXml,
+                         Data.FileStore.MercurialCommandServer
+    extensions:          FlexibleInstances
 
     if flag(maxcount) 
         cpp-options: -DUSE_MAXCOUNT
