Copyright | (c) 2010 Jasper Van der Jeugt (c) 2010-2011 Simon Meier |
---|---|
License | BSD3-style (see LICENSE) |
Maintainer | Simon Meier <[email protected]> |
Portability | GHC |
Safe Haskell | Trustworthy |
Language | Haskell98 |
Synopsis
- toLazyByteStringWith :: AllocationStrategy -> ByteString -> Builder -> ByteString
- data AllocationStrategy
- safeStrategy :: Int -> Int -> AllocationStrategy
- untrimmedStrategy :: Int -> Int -> AllocationStrategy
- smallChunkSize :: Int
- defaultChunkSize :: Int
- byteStringCopy :: ByteString -> Builder
- byteStringInsert :: ByteString -> Builder
- byteStringThreshold :: Int -> ByteString -> Builder
- lazyByteStringCopy :: ByteString -> Builder
- lazyByteStringInsert :: ByteString -> Builder
- lazyByteStringThreshold :: Int -> ByteString -> Builder
- flush :: Builder
- type BufferWriter = Ptr Word8 -> Int -> IO (Int, Next)
- data Next
- runBuilder :: Builder -> BufferWriter
- intHost :: Int -> Builder
- int16Host :: Int16 -> Builder
- int32Host :: Int32 -> Builder
- int64Host :: Int64 -> Builder
- wordHost :: Word -> Builder
- word16Host :: Word16 -> Builder
- word32Host :: Word32 -> Builder
- word64Host :: Word64 -> Builder
- floatHost :: Float -> Builder
- doubleHost :: Double -> Builder
Execution strategies
:: AllocationStrategy | Buffer allocation strategy to use |
-> ByteString | Lazy |
-> Builder |
|
-> ByteString | Resulting lazy |
Heavy inlining. Execute a Builder
with custom execution parameters.
This function is inlined despite its heavy code-size to allow fusing with
the allocation strategy. For example, the default Builder
execution
function toLazyByteString
is defined as follows.
{-# NOINLINE toLazyByteString #-} toLazyByteString = toLazyByteStringWith (safeStrategy
smallChunkSize
defaultChunkSize
) L.empty
where L.empty
is the zero-length lazy ByteString
.
In most cases, the parameters used by toLazyByteString
give good
performance. A sub-performing case of toLazyByteString
is executing short
(<128 bytes) Builder
s. In this case, the allocation overhead for the first
4kb buffer and the trimming cost dominate the cost of executing the
Builder
. You can avoid this problem using
toLazyByteStringWith (safeStrategy 128 smallChunkSize) L.empty
This reduces the allocation and trimming overhead, as all generated
ByteString
s fit into the first buffer and there is no trimming
required, if more than 64 bytes and less than 128 bytes are written.
data AllocationStrategy Source #
A buffer allocation strategy for executing Builder
s.
:: Int | Size of first buffer |
-> Int | Size of successive buffers |
-> AllocationStrategy | An allocation strategy that guarantees that at least half of the allocated memory is used for live data |
Use this strategy for generating lazy ByteString
s whose chunks are
likely to survive one garbage collection. This strategy trims buffers
that are filled less than half in order to avoid spilling too much memory.
:: Int | Size of the first buffer |
-> Int | Size of successive buffers |
-> AllocationStrategy | An allocation strategy that does not trim any of the filled buffers before converting it to a chunk |
Use this strategy for generating lazy ByteString
s whose chunks are
discarded right after they are generated. For example, if you just generate
them to write them to a network socket.
smallChunkSize :: Int Source #
The recommended chunk size. Currently set to 4k, less the memory management overhead
defaultChunkSize :: Int Source #
The chunk size used for I/O. Currently set to 32k, less the memory management overhead
Controlling chunk boundaries
byteStringCopy :: ByteString -> Builder Source #
Construct a Builder
that copies the strict ByteString
.
Use this function to create Builder
s from smallish (<= 4kb
)
ByteString
s or if you need to guarantee that the ByteString
is not
shared with the chunks generated by the Builder
.
byteStringInsert :: ByteString -> Builder Source #
Construct a Builder
that always inserts the strict ByteString
directly as a chunk.
This implies flushing the output buffer, even if it contains just
a single byte. You should therefore use byteStringInsert
only for large
(> 8kb
) ByteString
s. Otherwise, the generated chunks are too
fragmented to be processed efficiently afterwards.
byteStringThreshold :: Int -> ByteString -> Builder Source #
Construct a Builder
that copies the strict ByteString
s, if it is
smaller than the treshold, and inserts it directly otherwise.
For example, byteStringThreshold 1024
copies strict ByteString
s whose size
is less or equal to 1kb, and inserts them directly otherwise. This implies
that the average chunk-size of the generated lazy ByteString
may be as
low as 513 bytes, as there could always be just a single byte between the
directly inserted 1025 byte, strict ByteString
s.
lazyByteStringCopy :: ByteString -> Builder Source #
Construct a Builder
that copies the lazy ByteString
.
lazyByteStringInsert :: ByteString -> Builder Source #
Construct a Builder
that inserts all chunks of the lazy ByteString
directly.
lazyByteStringThreshold :: Int -> ByteString -> Builder Source #
Construct a Builder
that uses the thresholding strategy of byteStringThreshold
for each chunk of the lazy ByteString
.
Low level execution
type BufferWriter = Ptr Word8 -> Int -> IO (Int, Next) Source #
A BufferWriter
represents the result of running a Builder
.
It unfolds as a sequence of chunks of data. These chunks come in two forms:
- an IO action for writing the Builder's data into a user-supplied memory buffer.
- a pre-existing chunks of data represented by a strict
ByteString
While this is rather low level, it provides you with full flexibility in how the data is written out.
The BufferWriter
itself is an IO action: you supply it with a buffer
(as a pointer and length) and it will write data into the buffer.
It returns a number indicating how many bytes were actually written
(which can be 0
). It also returns a Next
which describes what
comes next.
After running a BufferWriter
action there are three possibilities for
what comes next:
Done | This means we're all done. All the builder data has now been written. |
More !Int BufferWriter | This indicates that there may be more data to write. It
gives you the next |
Chunk !ByteString BufferWriter | In addition to the data that has just been written into your buffer
by the |
runBuilder :: Builder -> BufferWriter Source #
Turn a Builder
into its initial BufferWriter
action.
Host-specific binary encodings
wordHost :: Word -> Builder Source #
Encode a single native machine Word
. The Word
is encoded in host order,
host endian form, for the machine you're on. On a 64 bit machine the Word
is an 8 byte value, on a 32 bit machine, 4 bytes. Values encoded this way
are not portable to different endian or word sized machines, without
conversion.