<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">Hello Haskellers,</p>
<p style="margin:0px 0px 1.2em!important">I’ve been trying to squeeze as much performance out of my code as possible and I’ve come to a point where can’t figure out what more I can do.</p>
<p style="margin:0px 0px 1.2em!important">Here is some example code:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248);white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important">blankEscapedChars :: MonadThrow m => Conduit BS.ByteString m BS.ByteString
blankEscapedChars = blankEscapedChars' ""

blankEscapedChars' :: MonadThrow m => BS.ByteString -> Conduit BS.ByteString m BS.ByteString
blankEscapedChars' rs = do
  mbs <- await
  case mbs of
    Just bs -> do
      let cs = if BS.length rs /= 0 then BS.concat [rs, bs] else bs
      let ds = fst (unfoldrN (BS.length cs) unescapeByteString (False, cs))
      yield ds
      blankEscapedChars' (BS.drop (BS.length ds) cs)
    Nothing -> when (BS.length rs > 0) (yield rs)
  where
    unescapeByteString :: (Bool, ByteString) -> Maybe (Word8, (Bool, ByteString))
    unescapeByteString (wasEscaped, bs) = case BS.uncons bs of
      Just (_, cs) | wasEscaped       -> Just (wUnderscore, (False, cs))
      Just (c, cs) | c /= wBackslash  -> Just (c, (False, cs))
      Just (c, cs)                    -> Just (c, (True, cs))
      Nothing                         -> Nothing
</code></pre><p style="margin:0px 0px 1.2em!important">The above function <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">blankEscapedChars</code> will go find all <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">\</code> characters and convert the following character to a <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">_</code>.  For a <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">1 MB</code> in memory JSON <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">ByteString</code>, it benches at about <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">6.6 ms</code></p>
<p style="margin:0px 0px 1.2em!important">In all my code the basic strategy is the same.  <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">await</code> for the next byte string, then use and <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">unfoldrN</code> to produce a new <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248)">ByteString</code> for yielding.</p>
<p style="margin:0px 0px 1.2em!important">Anyone know of a way to go faster?</p>
<p style="margin:0px 0px 1.2em!important">Cheers,</p>
<p style="margin:0px 0px 1.2em!important">-John</p>
<div title="MDH:SGVsbG8gSGFza2VsbGVycyw8ZGl2Pjxicj48L2Rpdj48ZGl2PkkndmUgYmVlbiB0cnlpbmcgdG8g
c3F1ZWV6ZSBhcyBtdWNoIHBlcmZvcm1hbmNlIG91dCBvZiBteSBjb2RlIGFzIHBvc3NpYmxlIGFu
ZCBJJ3ZlIGNvbWUgdG8gYSBwb2ludCB3aGVyZSBjYW4ndCBmaWd1cmUgb3V0IHdoYXQgbW9yZSBJ
IGNhbiBkby48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkhlcmUgaXMgc29tZSBleGFtcGxlIGNv
ZGU6PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5gYGA8L2Rpdj48ZGl2PjxkaXY+YmxhbmtFc2Nh
cGVkQ2hhcnMgOjogTW9uYWRUaHJvdyBtID0mZ3Q7IENvbmR1aXQgQlMuQnl0ZVN0cmluZyBtIEJT
LkJ5dGVTdHJpbmc8L2Rpdj48ZGl2PmJsYW5rRXNjYXBlZENoYXJzID0gYmxhbmtFc2NhcGVkQ2hh
cnMnICIiPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5ibGFua0VzY2FwZWRDaGFycycgOjogTW9u
YWRUaHJvdyBtID0mZ3Q7IEJTLkJ5dGVTdHJpbmcgLSZndDsgQ29uZHVpdCBCUy5CeXRlU3RyaW5n
IG0gQlMuQnl0ZVN0cmluZzwvZGl2PjxkaXY+YmxhbmtFc2NhcGVkQ2hhcnMnIHJzID0gZG88L2Rp
dj48ZGl2PiZuYnNwOyBtYnMgJmx0Oy0gYXdhaXQ8L2Rpdj48ZGl2PiZuYnNwOyBjYXNlIG1icyBv
ZjwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyBKdXN0IGJzIC0mZ3Q7IGRvPC9kaXY+PGRpdj4mbmJz
cDsgJm5ic3A7ICZuYnNwOyBsZXQgY3MgPSBpZiBCUy5sZW5ndGggcnMgLz0gMCB0aGVuIEJTLmNv
bmNhdCBbcnMsIGJzXSBlbHNlIGJzPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICZuYnNwOyBsZXQg
ZHMgPSBmc3QgKHVuZm9sZHJOIChCUy5sZW5ndGggY3MpIHVuZXNjYXBlQnl0ZVN0cmluZyAoRmFs
c2UsIGNzKSk8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgJm5ic3A7IHlpZWxkIGRzPC9kaXY+PGRp
dj4mbmJzcDsgJm5ic3A7ICZuYnNwOyBibGFua0VzY2FwZWRDaGFycycgKEJTLmRyb3AgKEJTLmxl
bmd0aCBkcykgY3MpPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7IE5vdGhpbmcgLSZndDsgd2hlbiAo
QlMubGVuZ3RoIHJzICZndDsgMCkgKHlpZWxkIHJzKTwvZGl2PjxkaXY+Jm5ic3A7IHdoZXJlPC9k
aXY+PGRpdj4mbmJzcDsgJm5ic3A7IHVuZXNjYXBlQnl0ZVN0cmluZyA6OiAoQm9vbCwgQnl0ZVN0
cmluZykgLSZndDsgTWF5YmUgKFdvcmQ4LCAoQm9vbCwgQnl0ZVN0cmluZykpPC9kaXY+PGRpdj4m
bmJzcDsgJm5ic3A7IHVuZXNjYXBlQnl0ZVN0cmluZyAod2FzRXNjYXBlZCwgYnMpID0gY2FzZSBC
Uy51bmNvbnMgYnMgb2Y8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgJm5ic3A7IEp1c3QgKF8sIGNz
KSB8IHdhc0VzY2FwZWQgJm5ic3A7ICZuYnNwOyAmbmJzcDsgLSZndDsgSnVzdCAod1VuZGVyc2Nv
cmUsIChGYWxzZSwgY3MpKTwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgSnVzdCAoYywg
Y3MpIHwgYyAvPSB3QmFja3NsYXNoICZuYnNwOy0mZ3Q7IEp1c3QgKGMsIChGYWxzZSwgY3MpKTwv
ZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgSnVzdCAoYywgY3MpICZuYnNwOyAmbmJzcDsg
Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOy0m
Z3Q7IEp1c3QgKGMsIChUcnVlLCBjcykpPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICZuYnNwOyBO
b3RoaW5nICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAm
bmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IC0mZ3Q7IE5vdGhpbmc8L2Rpdj48L2Rp
dj48ZGl2PmBgYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+VGhlIGFib3ZlIGZ1bmN0aW9uIGBi
bGFua0VzY2FwZWRDaGFyc2Agd2lsbCBnbyBmaW5kIGFsbCBgXGAgY2hhcmFjdGVycyBhbmQgY29u
dmVydCB0aGUgZm9sbG93aW5nIGNoYXJhY3RlciB0byBhIGBfYC4gJm5ic3A7Rm9yIGEgYDEgTUJg
IGluIG1lbW9yeSBKU09OIGBCeXRlU3RyaW5nYCwgaXQgYmVuY2hlcyBhdCBhYm91dCBgNi42IG1z
YDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PC9kaXY+PGRpdj5JbiBhbGwgbXkgY29kZSB0aGUg
YmFzaWMgc3RyYXRlZ3kgaXMgdGhlIHNhbWUuICZuYnNwO2Bhd2FpdGAgZm9yIHRoZSBuZXh0IGJ5
dGUgc3RyaW5nLCB0aGVuIHVzZSBhbmQgYHVuZm9sZHJOYCB0byBwcm9kdWNlIGEgbmV3IGBCeXRl
U3RyaW5nYCBmb3IgeWllbGRpbmcuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5BbnlvbmUga25v
dyBvZiBhIHdheSB0byBnbyBmYXN0ZXI/PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5DaGVlcnMs
PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4tSm9objwvZGl2PjxkaXY+PGJyPjwvZGl2Pg==" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>