Skip to content

Commit

Permalink
Builders: Implement non-host endianess writes using a single write. (#…
Browse files Browse the repository at this point in the history
…531)

We do this by swapping the byte order in memory before we write.
This speeds up int64BE by a factor of three.

(cherry picked from commit e38782a)
  • Loading branch information
AndreasPK authored and sjakobi committed Jul 25, 2022
1 parent f4b0227 commit e6a8b19
Showing 1 changed file with 6 additions and 68 deletions.
74 changes: 6 additions & 68 deletions Data/ByteString/Builder/Prim/Binary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,14 @@ word16BE :: FixedPrim Word16
#ifdef WORDS_BIGENDIAN
word16BE = word16Host
#else
word16BE = fixedPrim 2 $ \w p -> do
poke p (fromIntegral (shiftR w 8) :: Word8)
poke (p `plusPtr` 1) (fromIntegral w :: Word8)
word16BE = byteSwap16 >$< word16Host
#endif

-- | Encoding 'Word16's in little endian format.
{-# INLINE word16LE #-}
word16LE :: FixedPrim Word16
#ifdef WORDS_BIGENDIAN
word16LE = fixedPrim 2 $ \w p -> do
poke p (fromIntegral w :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR w 8) :: Word8)
word16LE = byteSwap16 >$< word16Host
#else
word16LE = word16Host
#endif
Expand All @@ -105,22 +101,14 @@ word32BE :: FixedPrim Word32
#ifdef WORDS_BIGENDIAN
word32BE = word32Host
#else
word32BE = fixedPrim 4 $ \w p -> do
poke p (fromIntegral (shiftR w 24) :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR w 16) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR w 8) :: Word8)
poke (p `plusPtr` 3) (fromIntegral w :: Word8)
word32BE = byteSwap32 >$< word32Host
#endif

-- | Encoding 'Word32's in little endian format.
{-# INLINE word32LE #-}
word32LE :: FixedPrim Word32
#ifdef WORDS_BIGENDIAN
word32LE = fixedPrim 4 $ \w p -> do
poke p (fromIntegral w :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR w 8) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR w 16) :: Word8)
poke (p `plusPtr` 3) (fromIntegral (shiftR w 24) :: Word8)
word32LE = byteSwap32 >$< word32Host
#else
word32LE = word32Host
#endif
Expand All @@ -134,64 +122,14 @@ word64BE :: FixedPrim Word64
#ifdef WORDS_BIGENDIAN
word64BE = word64Host
#else
#if WORD_SIZE_IN_BITS < 64
--
-- To avoid expensive 64 bit shifts on 32 bit machines, we cast to
-- Word32, and write that
--
word64BE =
fixedPrim 8 $ \w p -> do
let a = fromIntegral (shiftR w 32) :: Word32
b = fromIntegral w :: Word32
poke p (fromIntegral (shiftR a 24) :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR a 16) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR a 8) :: Word8)
poke (p `plusPtr` 3) (fromIntegral a :: Word8)
poke (p `plusPtr` 4) (fromIntegral (shiftR b 24) :: Word8)
poke (p `plusPtr` 5) (fromIntegral (shiftR b 16) :: Word8)
poke (p `plusPtr` 6) (fromIntegral (shiftR b 8) :: Word8)
poke (p `plusPtr` 7) (fromIntegral b :: Word8)
#else
word64BE = fixedPrim 8 $ \w p -> do
poke p (fromIntegral (shiftR w 56) :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR w 48) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR w 40) :: Word8)
poke (p `plusPtr` 3) (fromIntegral (shiftR w 32) :: Word8)
poke (p `plusPtr` 4) (fromIntegral (shiftR w 24) :: Word8)
poke (p `plusPtr` 5) (fromIntegral (shiftR w 16) :: Word8)
poke (p `plusPtr` 6) (fromIntegral (shiftR w 8) :: Word8)
poke (p `plusPtr` 7) (fromIntegral w :: Word8)
#endif
word64BE = byteSwap64 >$< word64Host
#endif

-- | Encoding 'Word64's in little endian format.
{-# INLINE word64LE #-}
word64LE :: FixedPrim Word64
#ifdef WORDS_BIGENDIAN
#if WORD_SIZE_IN_BITS < 64
word64LE =
fixedPrim 8 $ \w p -> do
let b = fromIntegral (shiftR w 32) :: Word32
a = fromIntegral w :: Word32
poke (p) (fromIntegral a :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR a 8) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR a 16) :: Word8)
poke (p `plusPtr` 3) (fromIntegral (shiftR a 24) :: Word8)
poke (p `plusPtr` 4) (fromIntegral b :: Word8)
poke (p `plusPtr` 5) (fromIntegral (shiftR b 8) :: Word8)
poke (p `plusPtr` 6) (fromIntegral (shiftR b 16) :: Word8)
poke (p `plusPtr` 7) (fromIntegral (shiftR b 24) :: Word8)
#else
word64LE = fixedPrim 8 $ \w p -> do
poke p (fromIntegral w :: Word8)
poke (p `plusPtr` 1) (fromIntegral (shiftR w 8) :: Word8)
poke (p `plusPtr` 2) (fromIntegral (shiftR w 16) :: Word8)
poke (p `plusPtr` 3) (fromIntegral (shiftR w 24) :: Word8)
poke (p `plusPtr` 4) (fromIntegral (shiftR w 32) :: Word8)
poke (p `plusPtr` 5) (fromIntegral (shiftR w 40) :: Word8)
poke (p `plusPtr` 6) (fromIntegral (shiftR w 48) :: Word8)
poke (p `plusPtr` 7) (fromIntegral (shiftR w 56) :: Word8)
#endif
word64LE = byteSwap64 >$< word64Host
#else
word64LE = word64Host
#endif
Expand Down

0 comments on commit e6a8b19

Please sign in to comment.