Closed parsonsmatt closed 2 months ago
It might be difficult to “drop in” lucid over xhtml onto a codebase that’s using strings everywhere and see an instant performance improvement due to the use of T.pack
, both explicit and the implicit conversions in toHtml
, as these will be creating lots of copies which means allocations.
I’m not sure that the GHC API gives you a FastString for many things in Haddock, because from there you could possibly jump straight to a Builder and avoid packing and re-encoding. But it might be possible to reduce pervasiveness of strings used internally within Haddock.
Another thing to check would be: are you writing the resulting HTML to eg a file directly via the builder, or are you converting to another intermediate string type?
The resulting HTML Builder
is written directly to disk. I did try to ensure that part was optimal. I do think that the use of String
everywhere is a cause for performance concern - pushing Text
as far back into the code as possible helped a bit, but the source parsers for everything are extremely slow and work over String
, so making it really fast is going to require more horizontal perfromance improvements rather than optimizing a single stage.
Hi, thank you for this PR, but Haddock now lives full-time in the GHC repository! Read more at https://discourse.haskell.org/t/haddock-now-lives-in-the-ghc-repository/9576.
Let me know if you feel it is still needed, and I'll migrate it. :)
I would encourage this or #1598 to be migrated.
This PR uses
lucid
for HTML generation, mostly as a test.Baseline
The baseline is the
ghc-9.4
branch , not myxhtml
builder patch.Lucid
Comparison
Very surprising!
lucid
is twice as slow.Now, I suspect that the
isNoHtml
thing is part of that. With the Lucid representation, we're actually having to run the wholeSeq Attribute -> Builder
, then converting thatBuilder
to a bytestring, and finally checking if it isnull
. This is very fast withxhtml
- theisNoHtml
check is anull
on a list.Banning
isNoHtml
Without
isNoHtml
to ruin the party, we get this run:That's a pretty great improvement!
I'm surprised to see that total allocations, max residency, and total memory are unchaged from baseline, despite 46% fewer allocations. I guess the streaming
[Char]
representation has some advantages.