diff options
| author | Tom Smeding <tom@tomsmeding.com> | 2026-08-02 21:07:55 +0200 |
|---|---|---|
| committer | Tom Smeding <tom@tomsmeding.com> | 2026-08-02 21:07:55 +0200 |
| commit | faff2c8249b1cc0342867dd22774301ae980647c (patch) | |
| tree | 0b8e7e68443a36855dfb20c8a2394a2351daece9 /src/ZNC/Parser.hs | |
| parent | 5c241aa67a927a1b1755c6691821421b742b141a (diff) | |
Slightly optimise realiseEvents
Diffstat (limited to 'src/ZNC/Parser.hs')
| -rw-r--r-- | src/ZNC/Parser.hs | 86 |
1 files changed, 43 insertions, 43 deletions
diff --git a/src/ZNC/Parser.hs b/src/ZNC/Parser.hs index edea7c8..6a4edc5 100644 --- a/src/ZNC/Parser.hs +++ b/src/ZNC/Parser.hs @@ -68,9 +68,9 @@ evRepSz = 22 -- | Retains the original ByteString. data RawEvents = RawEvents - ByteString -- original data parsed - Int -- actual number of events (may be smaller than allocated capacity in ByteArray#) - ByteArray# -- parsed array of `struct event`; pinned + !ByteString -- original data parsed + !Int -- actual number of events (may be smaller than allocated capacity in ByteArray#) + !ByteArray# -- parsed array of `struct event`; pinned parseLog :: ByteString -> [(HMS, Event)] parseLog = realiseEvents . parseLogRaw @@ -86,52 +86,52 @@ realiseEvents raw@(RawEvents _ nev _) = realiseEventsRange raw (0, nev) -- | This is a good list producer. Range is (inclusive, exclusive). {-# INLINE realiseEventsRange #-} realiseEventsRange :: RawEvents -> (Int, Int) -> [(HMS, Event)] -realiseEventsRange (RawEvents bs _ ba#) (startidx, endidx) = - [(deserialiseHMS i, deserialiseEvent i) | i <- [startidx .. endidx - 1]] +realiseEventsRange raws (startidx, endidx) = + [(deserialiseHMS raws i, deserialiseEvent raws i) | i <- [startidx .. endidx - 1]] + +-- These INLINE and NOINLINE are to ensure the produced list, as well as +-- the contained tuples, can get fused into the consumer, without bloating +-- up the consumer code. +{-# NOINLINE deserialiseHMS #-} +deserialiseHMS :: RawEvents -> Int -> HMS +deserialiseHMS (RawEvents _ _ ba#) i = HMS (byte 0) (byte 1) (byte 2) where - -- These INLINE and NOINLINE are to ensure the produced list, as well as - -- the contained tuples, can get fused into the consumer, without bloating - -- up the consumer code. - {-# NOINLINE deserialiseHMS #-} - deserialiseHMS :: Int -> HMS - deserialiseHMS i = HMS (byte 0) (byte 1) (byte 2) - where - byte :: Int -> Word8 - byte off = readWord8 (i * evRepSz + off) + byte :: Int -> Word8 + byte off = readWord8At ba# (i * evRepSz + off) - {-# NOINLINE deserialiseEvent #-} - deserialiseEvent :: Int -> Event - deserialiseEvent i = - case byte 3 of - 1 -> Join (textfield 0) (textfield 1) - 2 -> Part (textfield 0) (textfield 1) (textfield 2) - 3 -> Quit (textfield 0) (textfield 1) (textfield 2) - 4 -> ReNick (textfield 0) (textfield 1) - 5 -> Talk (textfield 0) (textfield 1) - 6 -> Notice (textfield 0) (textfield 1) - 7 -> Act (textfield 0) (textfield 1) - 8 -> Kick (textfield 0) (textfield 1) (textfield 2) - 9 -> Mode (textfield 0) (textfield 1) - 10 -> Topic (textfield 0) (textfield 1) - _ {- includes 0 -} -> ParseError - where - byte :: Int -> Word8 - byte off = readWord8 (i * evRepSz + off) +{-# NOINLINE deserialiseEvent #-} +deserialiseEvent :: RawEvents -> Int -> Event +deserialiseEvent (RawEvents bs _ ba#) i = + case byte 3 of + 1 -> Join (textfield 0) (textfield 1) + 2 -> Part (textfield 0) (textfield 1) (textfield 2) + 3 -> Quit (textfield 0) (textfield 1) (textfield 2) + 4 -> ReNick (textfield 0) (textfield 1) + 5 -> Talk (textfield 0) (textfield 1) + 6 -> Notice (textfield 0) (textfield 1) + 7 -> Act (textfield 0) (textfield 1) + 8 -> Kick (textfield 0) (textfield 1) (textfield 2) + 9 -> Mode (textfield 0) (textfield 1) + 10 -> Topic (textfield 0) (textfield 1) + _ {- includes 0 -} -> ParseError + where + byte :: Int -> Word8 + byte off = readWord8At ba# (i * evRepSz + off) - textfield :: Int -> Text - textfield n = - let offset = fromIntegral @Word32 @Int (readWord32 (i * evRepSz + 4 + 4 * n)) - len = fromIntegral @Word16 @Int (readWord16 (i * evRepSz + 16 + 2 * n)) - in TE.decodeUtf8Lenient (BS.take len (BS.drop offset bs)) + textfield :: Int -> Text + textfield n = + let offset = fromIntegral @Word32 @Int (readWord32At ba# (i * evRepSz + 4 + 4 * n)) + len = fromIntegral @Word16 @Int (readWord16At ba# (i * evRepSz + 16 + 2 * n)) + in TE.decodeUtf8Lenient (BS.take len (BS.drop offset bs)) - readWord32 :: Int -> Word32 - readWord32 (I# i#) = W32# (indexWord8ArrayAsWord32# ba# i#) +readWord32At :: ByteArray# -> Int -> Word32 +readWord32At ba# (I# i#) = W32# (indexWord8ArrayAsWord32# ba# i#) - readWord16 :: Int -> Word16 - readWord16 (I# i#) = W16# (indexWord8ArrayAsWord16# ba# i#) +readWord16At :: ByteArray# -> Int -> Word16 +readWord16At ba# (I# i#) = W16# (indexWord8ArrayAsWord16# ba# i#) - readWord8 :: Int -> Word8 - readWord8 (I# i#) = W8# (indexWord8Array# ba# i#) +readWord8At :: ByteArray# -> Int -> Word8 +readWord8At ba# (I# i#) = W8# (indexWord8Array# ba# i#) -- | The 'ByteString' is retained inside the 'RawEvents'. {-# NOINLINE parseLogRaw #-} |
