JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-4246

Excessive, repetitive, or unnecessary setAccessible calls could impact performance

    Details

    • Number of attachments :
      0

      Description

      From Toby Reyelts, of the Google AppEngine team:

      I've had a few moments to do some measuring on a sample Merb-based webapp that Ryan Brown gave me a while back. The only test I ran against the webapp was to load the default page that Merb presents. Some interesting things I see JRuby doing:

      1) Making ~6000 successful setAccessible calls
      2) Making ~530 failed setAccessible calls
      3) Making ~200 Method.invoke calls

      • AccessibleObject.setAccessible calls aren't free on App Engine. (They're not really slow, but neither are they blazing). Making 6000 of these during startup is likely chewing up hundreds of milliseconds worth of time.
      • Calls to AccessibleObject.setAccessible which fail are currently very expensive on App Engine - on the order of 50x as expensive. The interesting part about this is that almost every single one of these calls are against Object.clone and Object.finalize. Apparently JRuby isn't caching the results, and for some reason is trying to set them accessible over and over.
      • I see that the number of Method.invoke calls is very small compared to the total number of setAccessible calls. It looks like JRuby is doing something like eagerly calling setAccessible on every single method of every class that gets loaded.

      It seems like, with some very minor changes, there could be significant improvements to startup for JRuby on App Engine.

        Issue Links

          Activity

          Hide
          Charles Oliver Nutter added a comment -

          Ok, I'm going to mark this resolved. It turned out that we were eagerly calling setAccessible on all methods and constructors, so our existing lazy class initialization was not helping. We were also calling setAccessible on all public fields, which is a waste of time. Now we only call setAccessible in batches (grouped by named overloads) when actually initializing the class.

          Additional work on making things lazy would require breaking up the class initialization by method name as well as by "have you called any methods or instantiated these classes" like it is now, which is a larger change out of scope for this bug. The changes I made should reduce by half or more the number of setAccessible calls made, and potentially by a lot more if the existing lazy mechanisms are working well (and I have no reason to believe they are not).

          Show
          Charles Oliver Nutter added a comment - Ok, I'm going to mark this resolved. It turned out that we were eagerly calling setAccessible on all methods and constructors, so our existing lazy class initialization was not helping. We were also calling setAccessible on all public fields, which is a waste of time. Now we only call setAccessible in batches (grouped by named overloads) when actually initializing the class. Additional work on making things lazy would require breaking up the class initialization by method name as well as by "have you called any methods or instantiated these classes" like it is now, which is a larger change out of scope for this bug. The changes I made should reduce by half or more the number of setAccessible calls made, and potentially by a lot more if the existing lazy mechanisms are working well (and I have no reason to believe they are not).

            People

            • Assignee:
              Charles Oliver Nutter
              Reporter:
              Charles Oliver Nutter
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: