packages feed

fast-builder 0.1.0.2 → 0.1.1.0

raw patch · 4 files changed

+48/−12 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Data.ByteString.FastBuilder: hPutBuilderLen :: Handle -> Builder -> IO Int
+ Data.ByteString.FastBuilder.Internal: [queueBuffer] :: Queue -> !ForeignPtr Word8
+ Data.ByteString.FastBuilder.Internal: [queueStart] :: Queue -> !Int
+ Data.ByteString.FastBuilder.Internal: [queueTotal] :: Queue -> !Int
+ Data.ByteString.FastBuilder.Internal: hPutBuilderLen :: Handle -> Builder -> IO Int
- Data.ByteString.FastBuilder: hPutBuilderWith :: Handle -> Int -> Int -> Builder -> IO ()
+ Data.ByteString.FastBuilder: hPutBuilderWith :: Handle -> Int -> Int -> Builder -> IO Int
- Data.ByteString.FastBuilder.Internal: Queue :: !ForeignPtr Word8 -> !Int -> Queue
+ Data.ByteString.FastBuilder.Internal: Queue :: !ForeignPtr Word8 -> !Int -> !Int -> Queue
- Data.ByteString.FastBuilder.Internal: hPutBuilderWith :: Handle -> Int -> Int -> Builder -> IO ()
+ Data.ByteString.FastBuilder.Internal: hPutBuilderWith :: Handle -> Int -> Int -> Builder -> IO Int

Files

Data/ByteString/FastBuilder.hs view
@@ -74,6 +74,7 @@   , toLazyByteStringWith   , toStrictByteString   , hPutBuilder+  , hPutBuilderLen   , hPutBuilderWith    -- * Performance tuning
Data/ByteString/FastBuilder/Internal.hs view
@@ -36,6 +36,7 @@   , toLazyByteStringWith   , toStrictByteString   , hPutBuilder+  , hPutBuilderLen   , hPutBuilderWith    -- * Basic builders@@ -152,8 +153,14 @@       -- size limit is reached. After that, the destination switches       -- to a 'ThreadedSink'. --- | A mutable buffer. The 'Int' specifies where the data start.-data Queue = Queue !(ForeignPtr Word8) !Int{-start-}+-- | A mutable buffer.+data Queue = Queue+  { queueBuffer :: !(ForeignPtr Word8)+  , queueStart :: !Int+    -- ^ Starting position.+  , queueTotal :: !Int+    -- ^ Bytes written to the handle so far.+  }   -- TODO: this is not really needed  -- | A request from the driver thread to the builder thread.@@ -462,19 +469,30 @@  -- | Output a 'Builder' to a 'IO.Handle'. hPutBuilder :: IO.Handle -> Builder -> IO ()-hPutBuilder !h builder = hPutBuilderWith h 100 4096 builder+hPutBuilder !h builder = void $ hPutBuilderLen h builder+{-# INLINE hPutBuilder #-} +-- | Output a 'Builder' to a 'IO.Handle'. Returns the number of bytes written.+hPutBuilderLen :: IO.Handle -> Builder -> IO Int+hPutBuilderLen !h builder = hPutBuilderWith h 100 4096 builder+ -- | Like 'hPutBuffer', but allows the user to specify the initial -- and the subsequent desired buffer sizes. This function may be useful for -- setting large buffer when high throughput I/O is needed.-hPutBuilderWith :: IO.Handle -> Int -> Int -> Builder -> IO ()+hPutBuilderWith :: IO.Handle -> Int -> Int -> Builder -> IO Int hPutBuilderWith !h !initialCap !nextCap builder = do   fptr <- mallocForeignPtrBytes initialCap-  qRef <- newIORef $ Queue fptr 0+  qRef <- newIORef $ Queue+    { queueBuffer = fptr+    , queueStart =  0+    , queueTotal = 0+    }   let !base = unsafeForeignPtrToPtr fptr   cur <- runBuilder builder (HandleSink h nextCap qRef)     base (base `plusPtr` initialCap)   flushQueue h qRef cur+  Queue{ queueTotal = len } <- readIORef qRef+  return len  ---------------------------------------------------------------- -- builders@@ -647,7 +665,7 @@     HandleSink h nextCap queueRef -> do       cur <- getCur       io $ flushQueue h queueRef cur-      switchQueue queueRef $ max nextCap (I# n)+      switchQueue queueRef (max nextCap (I# n)) {-# NOINLINE getBytes_ #-}  -- | Return the remaining size of the current buffer, in bytes.@@ -715,26 +733,35 @@ -- the 'Queue'. flushQueue :: IO.Handle -> IORef Queue -> Ptr Word8 -> IO () flushQueue !h !qRef !cur = do-  Queue fptr start <- readIORef qRef+  Queue{ queueBuffer = fptr, queueStart = start, queueTotal = total }+    <- readIORef qRef   let !end = cur `minusPtr` unsafeForeignPtrToPtr fptr   when (end > start) $ do     S.hPut h $ S.fromForeignPtr fptr start (end - start)-    writeIORef qRef $ Queue fptr end+    writeIORef qRef Queue+      { queueBuffer = fptr+      , queueStart = end+      , queueTotal = total + end - start+      } --- | @switchQueue qRef minSize@ discards the old 'Queue' and sets up+-- | @switchQueue qRef minSize adv@ discards the old 'Queue' and sets up -- a new empty 'Queue' of at least @minSize@ large. If the old 'Queue' -- is large enough, it is re-used. switchQueue :: IORef Queue -> Int -> BuildM () switchQueue !qRef !minSize = do   end <- getCur-  Queue fptr _ <- io $ readIORef qRef+  Queue{ queueBuffer = fptr, queueTotal = total } <- io $ readIORef qRef   let !base = unsafeForeignPtrToPtr fptr   let !cap = end `minusPtr` base   newFptr <- if minSize <= cap     then return fptr     else io $ mallocForeignPtrBytes minSize   let !newBase = unsafeForeignPtrToPtr newFptr-  io $ writeIORef qRef $ Queue newFptr 0+  io $ writeIORef qRef Queue+    { queueBuffer = newFptr+    , queueStart = 0+    , queueTotal = total+    }   setCur newBase   setEnd $ newBase `plusPtr` max minSize cap 
fast-builder.cabal view
@@ -1,5 +1,5 @@ name:                fast-builder-version:             0.1.0.2+version:             0.1.1.0 synopsis:            Fast ByteString Builder description:         An efficient implementation of ByteString builder. It should be faster than                      the standard implementation in most cases.
tests/prop.hs view
@@ -196,6 +196,14 @@ prop_writeWrite w0 w1   = toStrictByteString (word8 w0 <> word8 w1) == BS.pack [w0, w1] +-- | hPutBuilderLen returns the correct number of bytes.+prop_length :: BuilderTree -> QC.Property+prop_length tree = QC.ioProperty $ IO.withFile "/dev/null" IO.WriteMode $ \h -> do+  let b = mkBuilder tree+  let len = BS.length $ toStrictByteString b+  len' <- hPutBuilderLen h b+  return $ len QC.=== len'+ return []  main :: IO ()