-
Notifications
You must be signed in to change notification settings - Fork 188
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
Report polymorphism for sprintf
nodes.
#3537
Conversation
@@ -1665,6 +1665,7 @@ private static RubyString finishFormat(Node node, int formatLength, BytesResult | |||
|
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.
We should remove the @ReportPolymorphism
on SprintfNode above, it has no effect since there is a single specialization instance possible (I filed GR-53454 for Truffle to warn this).
Alternatively we could mark the method as Split.ALWAYS, I think that's a little better because then it just splits eagerly vs only when creating a second specialization instance of formatCached
(and force splitting cannot be put on the wrong node like before this PR, unlike @ReportPolymorphism
).
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.
@andrykonchin Could you integrate this and add an extra commit removing the two @ReportPolymorphism
and adding always split on the @CoreMethod
?
It seems good to also check other cases of pack/unpack/format/sprintf/etc to make sure they are correct too.
One easy way to find them seems callers of global search RootCallTarget compile(
.
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.
On second thought, It seems good to keep the @ReportPolymorphism
added in this PR, because then if someone does:
def myformat(format, *args)
sprintf format, *args
end
myformat "%d", 1
myformat "%f", 3.14
it would correctly split, and wouldn't with only the always_split.
But let's always split SprintfNode
since we know we'll want to split that one anyway, and the earlier the better for startup/warmup/footprint.
…ck1}, IO#printf core methods and rb_tr_sprintf C function
While looking at the performance of a large Rails application, I saw that we were creating new
CallTarget
on each call toString#%
. The generic specialization compiles thesprintf
expression from scratch on each call, resulting in the creation of a new call target.The
sprintf
code can be invoked in a few different ways, but the one that stood out to me wasString#%
. Rails will create a request ID for each request to make tracking logs and such easier. The ActiveSupport code for creating the UUID uses a static format string, but thesprintf
nodes are already megamorphic by the time this code is called. I saw it go megamorphic by loading the URI library.I suspect format strings are mostly static and splitting would make most call sites monomorphic. This simple change demonstrably splits with the following example:
For call sites with > 3 format strings we could add a global cache, like we do for regular expressions. That could cut down on the creation of unique call targets, but that's out of scope for this PR and I don't have any evidence of it being a real world problem at the moment.