/ jruby Public
Fix wrong method lookup cache used when class is prepended #4581
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge.
While benchmarking a @Talkdesk JRuby application during our recent
hackaton, I noticed quite a lot of thread contention in a workload where
there should be no shared data.
Stack traces showed that there was contention while performing writes to
the method lookup cache:
I ended up instrumenting the JRuby code and noticed that this kept
happening (on this workload) for calls to
which happened quite often and never seemed to be cached.
But why were threads repeatedly failing to lookup
#to_ary, saving it
on the cache, and then not finding it the next time around?
Every instance of the
RubyModuleclass keeps a method lookup cache in
myCachedMethodsand normally reads and writes to it. But
RubyModuleinstance keeps a reference called
methodLocationto the object where it keeps its methods.
methodLocationis set to
its own methods), but in some cases, e.g. when a class is prepended,
methodLocationchanges, and points elsewhere.
The problem here is that when looking up on the
cacheHitmethod always checks the local
addToCachewrites to the cache inside the
reference. This means that normally the method cache works fine as
same, but when
methodLocationchanges, the cache reads will never find
the correct cached method.
As a fix, I updated the
cacheHitmethod to also read from
I believe this is enough to fix the issue (and is a correct fix), but feedback is
very welcome as I'm still rather noob in the codebase.
Thanks go to @Talkdesk for letting me work on making JRuby kick even
Included below are my test cases and results from executing them.
Single-threaded performance impact test-case:
Multi-threaded contention test case:
Thread state in VisualVM, without fix, without prepending
Thread state in VisualVM, without fix, prepending
Thread state in VisualVM, with fix, prepending
(Back to normal)