@@ -153,8 +153,9 @@ encodeUtf8 (Text arr off len) = unsafePerformIO $ do
153153 where
154154 loop n1 m1 ptr = go n1 m1
155155 where
156+ offLen = off + len
156157 go !n !m
157− | n == off+len = return (PS fp 0 m)
158+ | n == offLen = return (PS fp 0 m)
158159 | otherwise = do
159160 let poke8 k v = poke (ptr `plusPtr` k) (fromIntegral v :: Word8)
160161 ensure k act
@@ -168,8 +169,17 @@ encodeUtf8 (Text arr off len) = unsafePerformIO $ do
168169 {-# INLINE ensure #-}
169170 case A.unsafeIndex arr n of
170171 w| w <= 0x7F -> ensure 1 $ do
171− poke8 m w
172− go (n+1) (m+1)
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
182+ ascii (n+1) (m+1)
173183 | w <= 0x7FF -> ensure 2 $ do
174184 poke8 m $ (w `shiftR` 6) + 0xC0
175185 poke8 (m+1) $ (w .&. 0x3f) + 0x80