Skip to content

Create strict bytestrings from FixedPrim with zero copy #666

Open
@lykahb

Description

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

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions