groovy
  1. groovy
  2. GROOVY-5249

Avoid unnecessary locking in ClassInfo.getMetaClass

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.3.0-beta-1, 2.2.3
    • Component/s: groovy-runtime
    • Labels:
      None
    • Environment:
      Linux 64-bit, Java 1.6, Tomcat, Grails
    • Number of attachments :
      2

      Description

      We have a Grails application serving hundreds of requests per second and this seems to be the most critical hot spot for us. Under high load, most threads are blocked in the following call stack:

      "http-apr-8080"-exec-144
      sun.misc.Unsafe.park(Native Method)
      java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
      java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
      java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
      java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
      org.codehaus.groovy.util.LockableObject.lock(LockableObject.java:34)
      org.codehaus.groovy.reflection.ClassInfo.lock(ClassInfo.java:268)
      org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:193)
      org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:214)
      org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:747)
      org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:780)
      org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:772)
      org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToBoolean(DefaultTypeTransformation.java:156)
      org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.booleanUnbox(DefaultTypeTransformation.java:65)
      

      Grails uses InvokerHelper a lot, which calls ClassInfo.getMetaClass which uses locking. This is stop-the-world lock affecting all threads (they all hit the same ClassInfo instance). Note that 99,999% of time the locking is useless as nothing is modified (typically all metaclasses getting modified on startup).

      There are several related tickets: GROOVY-3557 and GROOVY-5059, not really solving the issue.

      The solution could be to use more fine-grained locks (ReadWriteLock) or Atomics. Should be easy to implement, but need to isolate modification part from read-only parts.

      Doing so can be a good boost to overall Grails performance.

      1. mc.patch
        2 kB
        blackdrag blackdrag
      2. mc.patch
        1 kB
        blackdrag blackdrag

        Activity

        Show
        Lari Hotari added a comment - patch backported to Groovy 2.0.8 : https://github.com/lhotari/groovy-core/compare/GROOVY_2_0_8...GROOVY-5249-backport.patch , commits: https://github.com/lhotari/groovy-core/compare/GROOVY_2_0_8...GROOVY-5249-backport
        Hide
        Fedor Belov added a comment -

        Hi. We have applied this patch on our production server and it works much, much better

        Show
        Fedor Belov added a comment - Hi. We have applied this patch on our production server and it works much, much better
        Hide
        blackdrag blackdrag added a comment -

        you mean the change from github?

        Show
        blackdrag blackdrag added a comment - you mean the change from github?
        Hide
        Fedor Belov added a comment - - edited

        this one -> https://github.com/lhotari/groovy-core/compare/GROOVY_2_0_8...GROOVY-5249-backport.patch
        but it doesn't really differ from unofficial one - https://jira.codehaus.org/secure/attachment/58665/mc.patch - it also works. Just it breaks 1 of 6000 groovy tests

        Show
        Fedor Belov added a comment - - edited this one -> https://github.com/lhotari/groovy-core/compare/GROOVY_2_0_8...GROOVY-5249-backport.patch but it doesn't really differ from unofficial one - https://jira.codehaus.org/secure/attachment/58665/mc.patch - it also works. Just it breaks 1 of 6000 groovy tests
        Hide
        blackdrag blackdrag added a comment -

        I applied the patch in a slightly modified version

        Show
        blackdrag blackdrag added a comment - I applied the patch in a slightly modified version

          People

          • Assignee:
            blackdrag blackdrag
            Reporter:
            Serge P. Nekoval
          • Votes:
            13 Vote for this issue
            Watchers:
            14 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: