-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make 'Terminal.renderLazy' lazy #176
Conversation
Good question! I guess a somewhat lasting solution would be to port the Does that sound reasonable? |
Certainly does. I probably won't get around to it until next week though. |
Well... We actually seem to be looking at a more than 2x speedup. Although, the benchmark data doesn't currently actually contain any annotations. I may add some and see what happens. |
Wow! Any idea why?
Yes, please do! |
Not really. All I'd say is that the old implementation is in |
I've played around with this a bit, and adding annotations only amplifies the difference. As does using The question now is which benchmarks are worth keeping around. We've got a lot of choices:
And using annotations also means using an algorithm other than |
Interesting. Have you looked at the Core to get more insight into the reason for the performance difference?
I don't care too much about that, although it's a nice baseline. It might be nice to include
Heavy annotations seem most interesting to me.
Oops! I didn't know that. Let's use |
I've updated the benchmark with
Nope. I don't have any experience with reading Core, and personally I'm happy to just defer to the magical black box that is GHC on this one. |
Nice work, @georgefst! Could you paste the benchmark results with the old and new implementations here? Regarding correctness: I'm unsure how much we can rely on the few doctests in |
@sjakobi Well, there's:
So I'm reasonably confident. |
Old implementation:
New version:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've stared at the Core a bit, but the differences are too large for a visual diff to be useful. Profiling might get us better insights into the performance differences, but I'm fine with just accepting the speedups. :)
renderedProg = (renderLazy . layoutPretty defaultLayoutOptions { layoutPageWidth = Unbounded } . prettyProgram) prog | ||
(progLines, progWidth) = let l = TL.lines renderedProg in (length l, maximum (map TL.length l)) | ||
putDoc ("Program size:" <+> pretty progLines <+> "lines, maximum width:" <+> pretty progWidth) | ||
|
||
let render :: (SimpleDocStream AnsiStyle -> TL.Text) -> Program -> TL.Text | ||
render r = r . layoutPretty defaultLayoutOptions . prettyProgram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's better use the Unbounded
PageWidth
– that should be much cheaper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, why benchmark the layouting? Better limit it to the rendering, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, why benchmark the layouting? Better limit it to the rendering, no?
I think we'd an instance NFData (SimpleDocStream AnsiStyle)
, which we can't auto-derive since we can't provide an orphan Generic
for AnsiStyle
, as it's opaque.
Anyway, it's done this way in the prettyprinter
benchmark this was based on, perhaps for the same reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought NFData
was only needed for the output, which is Text
?!
Adding NFData
and/or Generic
instances sounds like a good idea though. Feel free to make an issue!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps I'm misunderstanding how it works, but I thought that to accurately benchmark the rendering, we'd first have to force the input to that stage, which would be SimpleDocStream
.
@sjakobi The review comments I haven't replied to all relate to things that were copy-pasted from the benchmark from the core library. I'm happy to implement all your suggestions, unless you can see any reason not to. Presumably any backwards compatibility issues would be caught by CI? |
By which I mean, specifically, compiling with old GHCs. |
Yeah, we build the benchmarks in a few CI jobs, and I don't really care about the compatibility of the benchmarks with older GHC versions. So if you could clean up these wibbles a bit, that would be appreciated. @quchen Modulo the mentioned wibbles, this looks ready to go to me. Would you like to review, too? |
LGTM. The new code is much prettier and easier to understand than the ST-based version as well, and if the benchmark shows an improvement it’s a good change. |
What's the status now, @georgefst? Is this ready?! :) Have the benchmark results changed? |
Oh, BTW, a question for a suspected native English speaker: Is "wibble" a proper word and appropriate where I used it here? I think I saw SPJ use it but I'm actually not sure whether I'm using it right. :) |
Yes it's ready, unless we care about the one remaining review comment. I'd be happy to leave it as-is, seeing as it's no worse than the existing benchmark in the core library.
Slight speedup with |
I can't find any actual definition of it, but somehow I instantly knew what you meant. And I can't think of a good alternative, although "quibble" and "foible" are somewhat related. English is a silly language, and I've noticed SPJ is a fairly creative user of it. Anyway, it amused me because it reminded me of a scene from a classic TV show, which is, as it happens, what almost all references to "wibble" on the web seem to refer to. |
Thanks for all the work, @georgefst, and also the explanation for "wibble"! :) |
FYI regarding the release: #181 |
Fixes #175.
This is the non-monadic implementation, as requested by @sjakobi, which means a bit of extra parameter passing, but no big difference.
Any suggestions on how to benchmark this?