-
Notifications
You must be signed in to change notification settings - Fork 184
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
Cache results of Cmts.preserve #1766
Conversation
MaxRSS does not change too much when formatting |
aa60006
to
c3268d6
Compare
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.
The performance improvement is impressive, it looks good to me, thanks!
lib/Fmt_ast.ml
Outdated
type c = | ||
{ conf: Conf.t | ||
; debug: bool | ||
; source: Source.t | ||
; cmts: Cmts.t | ||
; fmt_code: Conf.t -> string -> (Fmt.t, unit) Result.t } | ||
; fmt_code: Conf.t -> string -> (Fmt.t, unit) Result.t | ||
; layout_cache: Layout_cache.t } |
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'm not sure it's worth to add this field to the type c, as we don't need to pass it to every function, it's only used by Cmts.preserve, why not add it to Cmts.t and directly modify the implementation of Cmts.preserve?
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 did so because it's not really related to comment handling, but yes we can do that.
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.
Thanks!
The `preserve` function returns a string with the layout of a part of the AST. It is used in several places to determine if a subpart has a break for example. This can be a problem when these constructions are nested, since laying out the external construction requires laying out the internal ones first, and this creates quadratic behavior. This is solved by caching the results of these intermediate layouts. This cache is unbounded so there are bad corner cases. At worst, each cached point is associated to the result string which could mean quadratic memory consumption. Some ways to fix this: - use a LRU cache like the one from `core_kernel` - store only a summary rather than the full string (length, number of lines, max indent) In addition to ocaml-ppx#1750, a similar case can be triggered using nested cases. It seems that `expression_width` would be affected but I have not been able to reproduce that using that code path. Closes ocaml-ppx#1750
The
preserve
function returns a string with the layout of a part of the AST. It is used in several places to determine if a subpart has a break for example.This can be a problem when these constructions are nested, since laying out the external construction requires laying out the internal ones first, and this creates quadratic behavior.
This is solved by caching the results of these intermediate layouts. This cache is unbounded so there are bad corner cases. At worst, each cached point is associated to the result string which could mean quadratic memory consumption.
Some ways to fix this:
core_kernel
In addition to #1750, a similar case can be triggered using nested cases. It seems that
expression_width
would be affected but I have not been able to reproduce that using that code path, so this part stays not cached.Closes #1750