Skip to content

Commit

Permalink
Make specialized parsers for Word32 and Word64. (#278)
Browse files Browse the repository at this point in the history
Previously they were implemented by a loop that didn't optimize well.

This speeds up the benchmark from #277 (decoding repeated floats)
by a factor of 2.6x.  Specifically, the `float-packed/decode` and `float-unpacked/decode` benchmarks dropped from ~225us to ~85us.
  • Loading branch information
judah authored and blackgnezdo committed Dec 13, 2018
1 parent 1f2ede2 commit 8dc5e85
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
26 changes: 16 additions & 10 deletions proto-lens/src/Data/ProtoLens/Encoding/Bytes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ module Data.ProtoLens.Encoding.Bytes(
-- * Integral types
getVarInt,
putVarInt,
anyBits,
getFixed32,
getFixed64,
putFixed32,
putFixed64,
-- * Floating-point types
Expand Down Expand Up @@ -88,15 +89,20 @@ putVarInt n
<> putVarInt (n `shiftR` 7)

-- | Little-endian decoding function.
anyBits :: forall a . (Num a, FiniteBits a) => Parser a
anyBits = loop 0 0
where
size = finiteBitSize (undefined :: a)
loop !w !n
| n >= size = return w
| otherwise = do
b <- anyWord8
loop (w .|. shiftL (fromIntegral b) n) (n+8)
getFixed32 :: Parser Word32
getFixed32 = do
b1 <- anyWord8
b2 <- anyWord8
b3 <- anyWord8
b4 <- anyWord8
return $ ((fromIntegral b4 `shiftL` 8 + fromIntegral b3)
`shiftL` 8 + fromIntegral b2) `shiftL` 8 + fromIntegral b1

getFixed64 :: Parser Word64
getFixed64 = do
x <- getFixed32
y <- getFixed32
return $ fromIntegral y `shiftL` 32 + fromIntegral x

putFixed32 :: Word32 -> Builder
putFixed32 = word32LE
Expand Down
4 changes: 2 additions & 2 deletions proto-lens/src/Data/ProtoLens/Encoding/Reflected/Wire.hs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ instance Ord WireValue where

getWireValue :: WireType a -> Parser a
getWireValue VarInt = getVarInt
getWireValue Fixed64 = anyBits
getWireValue Fixed32 = anyBits
getWireValue Fixed64 = getFixed64
getWireValue Fixed32 = getFixed32
getWireValue Lengthy = getVarInt >>= getBytes . fromIntegral
getWireValue StartGroup = return ()
getWireValue EndGroup = return ()
Expand Down

0 comments on commit 8dc5e85

Please sign in to comment.