on master help sign in
Improve ASCII encoding performance in a safer way.
a31c0f7Bryan O'Sullivan
Data/Text/Encoding.hs+13−3
@@ -153,8 +153,9 @@ encodeUtf8 (Text arr off len) = unsafePerformIO $ do
153 where
153 where
154 loop n1 m1 ptr = go n1 m1
154 loop n1 m1 ptr = go n1 m1
155 where
155 where
156+ offLen = off + len
156 go !n !m
157 go !n !m
157− | n == off+len = return (PS fp 0 m)
158+ | n == offLen = return (PS fp 0 m)
158 | otherwise = do
159 | otherwise = do
159 let poke8 k v = poke (ptr `plusPtr` k) (fromIntegral v :: Word8)
160 let poke8 k v = poke (ptr `plusPtr` k) (fromIntegral v :: Word8)
160 ensure k act
161 ensure k act
@@ -168,8 +169,17 @@ encodeUtf8 (Text arr off len) = unsafePerformIO $ do
168 {-# INLINE ensure #-}
169 {-# INLINE ensure #-}
169 case A.unsafeIndex arr n of
170 case A.unsafeIndex arr n of
170 w| w <= 0x7F -> ensure 1 $ do
171 w| w <= 0x7F -> ensure 1 $ do
171− poke8 m w
172+ poke (ptr `plusPtr` m) (fromIntegral w :: Word8)
173+ -- A single ASCII octet is likely to start a run of
174+ -- them. We see better performance when we
175+ -- special-case this assumption.
176+ let ascii !t !u
177+ | t == offLen || u == size || v >= 0x80 = go t u
178+ | otherwise = do
179+ poke (ptr `plusPtr` u) (fromIntegral v :: Word8)
180+ ascii (t+1) (u+1)
181+ where v = A.unsafeIndex arr t
172− go (n+1) (m+1)
182+ ascii (n+1) (m+1)
173 | w <= 0x7FF -> ensure 2 $ do
183 | w <= 0x7FF -> ensure 2 $ do
174 poke8 m $ (w `shiftR` 6) + 0xC0
184 poke8 m $ (w `shiftR` 6) + 0xC0
175 poke8 (m+1) $ (w .&. 0x3f) + 0x80
185 poke8 (m+1) $ (w .&. 0x3f) + 0x80