Skip to content

Create strict bytestrings from FixedPrim with zero copy #666

@lykahb

Description

@lykahb

To turn a FixedPrim into a strict ByteString, with the current public interface I can do something like this:

myTypePrim :: FixedPrim MyType

myTypeToLazyByteString :: MyType -> BL.ByteString
myTypeToLazyByteString =
    -- Some kind of allocation strategy to create a chunk of desired size
    BB.toLazyByteStringWith (BB.untrimmedStrategy 36 BB.defaultChunkSize) mempty
  . BBP.primFixed myTypePrim

-- Makes a copy with memcmp
myTypeToStrictByteString :: MyType -> BS.ByteString
myTypeToStrictByteString = toStrict . myTypeToLazyByteString

Once primFixed :: FixedPrim a -> a -> Builder converts a value to Builder, there are only utilities to convert it into a lazy bytestring.

One alternative is to use runF :: FixedPrim a -> a -> Ptr Word8 -> IO () together with create :: create :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString but that relies on two internal modules Data.ByteString.Builder.Prim.Internal and Data.ByteString.Internal.

I propose three solutions:

  1. Create function Builder -> Ptr Word8 -> IO ()
  2. Export runF :: FixedPrim a -> a -> Ptr Word8 -> IO () from the public module Data.ByteString.Builder.Prim.
  3. Create function primToByteString :: FixedPrim a -> a -> ByteString that creates a strict bytestring right away.

For both 1 and 2 the code would rely on the create from the semi-public module Data.ByteString.Internal.

For the context, the benchmarking in haskell-hvr/uuid#80 shows that the overhead of copy from toStrict slows down the conversion by 40% (28ns vs 20ns).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions