You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Aman Jain <am...@adeptia.com> on 2017/08/09 16:58:13 UTC

Lock contention in Groovy Shell interpreter under high load

Hello,

We are evaluating GroovyShell <http://groovy-lang.org/download.html>
interpreter
(v2.4) in our application for dynamically executing standard Java syntax.

Earlier, we were using Java BeanShell Interpreter for it, but it has an
issue
<https://stackoverflow.com/questions/45450947/lock-contention-in-java-beanshell-interpreter-under-high-load/45451768#45451768>
under
high load which prompted us to look for an alternative such as Groovy.

We are seeing thread lock contention when multiple threads execute the
below sample code simultaneously. We have multiple threads in the blocked
state which is degrading application performance.

My questions are:

   1. Has anyone experienced such problem? If yes, can you please suggest
   any possible resolution for it? I googled around for this problem and few
   blogs suggested to cache groovy Script object. Is Script object
   thread-safe? Moreover, I need to bind variables to Scriptobject (via
   groovy Binding object, which is different for each execution in
   different threads), so I don't think caching groovy Script object is a
   viable option.
   2. Are there any best practices that I need to follow while using Groovy
   Shell interpreter with Java?

PFA, sample code, and blocked thread call stack.

Let me know if you need more information. Thanks in advance for your time.

Regards,
Aman

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Jochen Theodorou <bl...@gmx.org>.
On 10.08.2017 20:40, Aman Jain wrote:
> Thank you, Jochen! It is very helpful.
> 
> So, what I understand is that I can cache either the Script (evalScript) 
> *or* Script Class (evalScript.getClass()) instances in my application 
> code and reuse them.

well, since you put the "or" in bold I tend to think you think this is 
an exclusive choice. You can use both if you want. Depends really on if 
it makes sense for you or not. You will always have one class, you will 
always need x instances for x parallel operations. If you cache the 
instance, you indirectly cache the class. The only factor then is if I 
make the instances each time fresh, or produce only x. Producing only x 
instances will have a little bit better results, but then you have to 
have a clean up strategy for the pool as well. Instance and class go 
together... so not really either-or... but of course nothing is really 
for free

> I tried by caching Script Class (evalScript.getClass()) instance and 
> reuse it in my code and the results are much better. For each thread, I 
> am retrieving the Script Class from my cache and generating its new 
> instance by calling scriptClass.newInstance()

ok

> Does above caching of Script Class (evalScript.getClass()) instance in 
> my application code can cause any memory leak or delayed clean-up of the 
> generated classes and meta classes (as you mentioned in your last point)?

nothing to worry about. The problem starts when you have potentially 100 
thousands of such classes (*not* instances)

bye Jochen

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Jochen Theodorou <bl...@gmx.org>.
On 10.08.2017 20:40, Aman Jain wrote:
> Thank you, Jochen! It is very helpful.
> 
> So, what I understand is that I can cache either the Script (evalScript) 
> *or* Script Class (evalScript.getClass()) instances in my application 
> code and reuse them.

well, since you put the "or" in bold I tend to think you think this is 
an exclusive choice. You can use both if you want. Depends really on if 
it makes sense for you or not. You will always have one class, you will 
always need x instances for x parallel operations. If you cache the 
instance, you indirectly cache the class. The only factor then is if I 
make the instances each time fresh, or produce only x. Producing only x 
instances will have a little bit better results, but then you have to 
have a clean up strategy for the pool as well. Instance and class go 
together... so not really either-or... but of course nothing is really 
for free

> I tried by caching Script Class (evalScript.getClass()) instance and 
> reuse it in my code and the results are much better. For each thread, I 
> am retrieving the Script Class from my cache and generating its new 
> instance by calling scriptClass.newInstance()

ok

> Does above caching of Script Class (evalScript.getClass()) instance in 
> my application code can cause any memory leak or delayed clean-up of the 
> generated classes and meta classes (as you mentioned in your last point)?

nothing to worry about. The problem starts when you have potentially 100 
thousands of such classes (*not* instances)

bye Jochen

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Aman Jain <am...@adeptia.com>.
Thank you, Jochen! It is very helpful.

So, what I understand is that I can cache either the Script (evalScript)
*or* Script Class (evalScript.getClass()) instances in my application code
and reuse them.

I tried by caching Script Class (evalScript.getClass()) instance and reuse
it in my code and the results are much better. For each thread, I am
retrieving the Script Class from my cache and generating its new instance
by calling scriptClass.newInstance()

Does above caching of Script Class (evalScript.getClass()) instance in my
application code can cause any memory leak or delayed clean-up of the
generated classes and meta classes (as you mentioned in your last point)?

Thanks,
Aman

On Thu, Aug 10, 2017 at 5:53 AM, Jochen Theodorou <bl...@gmx.org> wrote:

> Just for reference...this seems to be https://stackoverflow.com/ques
> tions/45578426/lock-contention-in-groovy-shell-interpreter-under-high-load
>
> more inline
>
> On 09.08.2017 18:58, Aman Jain wrote:
>
>> Hello,
>>
>> We are evaluating GroovyShell <http://groovy-lang.org/download.html>
>> interpreter (v2.4) in our application for dynamically executing standard
>> Java syntax.
>>
>> Earlier, we were using Java BeanShell Interpreter for it, but it has an
>> issue <https://stackoverflow.com/questions/45450947/lock-contentio
>> n-in-java-beanshell-interpreter-under-high-load/45451768#45451768> under
>> high load which prompted us to look for an alternative such as Groovy.
>>
>> We are seeing thread lock contention when multiple threads execute the
>> below sample code simultaneously. We have multiple threads in the blocked
>> state which is degrading application performance.
>>
>
> I am missing the counter part, the one that owns the lock. but looking at
>
>     java.lang.Thread.State: BLOCKED (on object monitor)
>>     at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
>>         - waiting to lock <0x00000007bc425e40> (a java.lang.Object)
>>         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
>>         at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
>>
>
> my strong assumption would be, that the counter part is also in
> java.lang.ClassLoader. My guess would be, that we are currently trying to
> load a class, probably from some other thread. If you have code like
>
> static String script = "int y = x * x; System.out.println(\"** value of y
>> ** :: \" + y ); ";
>>
>> GroovyShell gs = new GroovyShell();
>> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
>> // bind variables
>> Binding binding = new Binding();
>> binding.setVariable("x", 5);
>> evalScript.setBinding(binding);
>> // invoke eval method
>> evalScript.invokeMethod("evalMethod", null);
>>
>
> you would with each thread execution do a new compilation, which is where
> the majority of those class look-ups is coming from. The script form
> example contains System, which will be looked-up in maybe 10 variants
> before the compiler is happy. That makes 9 false look-ups. Multiply this
> with a hundred threads and you get 900 look-ups for classes, that actually
> do not exist. So the goal would be reuse. My suggestion would be then:
>
> for all threads:
>
> static String script = "int y = x * x; System.out.println(\"** value of y
>> ** :: \" + y ); ";
>>
>> GroovyShell gs = new GroovyShell();
>> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
>>
>
> in each thread:
>
> // bind variables
> Binding binding = new Binding();
> binding.setVariable("x", 5);
> Script threadEvalScript = InvokerHelper.createScript(evalScript.getClas(),
> binding);
> // invoke eval method
> threadEvalScript.invokeMethod("evalMethod", null);
>
> Even better would be of course to make a pool of script instances and use
> them from there
>
>
> My questions are:
>>
>>  1. Has anyone experienced such problem? If yes, can you please suggest
>>     any possible resolution for it? I googled around for this problem
>>     and few blogs suggested to cache groovy |Script| object. Is
>>     |Script| object thread-safe? Moreover, I need to bind variables to
>>     |Script|object (via groovy |Binding| object, which is different for
>>     each execution in different threads), so I don't think caching
>>     groovy |Script| object is a viable option.
>>
>
> You have to understand that there is the script and the binding. Ideally
> the script itself stores all the state in the binding. Then you need one
> combination of script and binding per thread that is concurrently running.
> How you can do that I tried to show above already a bit.
>
> btw, Binding is not thread-safe, but nothing prevents you from
> implementing your own Binding, that is. But given your statement, that the
> Binding is different each time I do not think there is a problem with this.
>
>  2. Are there any best practices that I need to follow while using
>>     Groovy Shell interpreter with Java?
>>
>
> Biggest problem normally is the delayed clean-up of the generated classes
> and meta classes, but this should not concern you here, once you managed to
> reuse the script class.
>
> bye Jochen
>

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Aman Jain <am...@adeptia.com>.
Thank you, Jochen! It is very helpful.

So, what I understand is that I can cache either the Script (evalScript)
*or* Script Class (evalScript.getClass()) instances in my application code
and reuse them.

I tried by caching Script Class (evalScript.getClass()) instance and reuse
it in my code and the results are much better. For each thread, I am
retrieving the Script Class from my cache and generating its new instance
by calling scriptClass.newInstance()

Does above caching of Script Class (evalScript.getClass()) instance in my
application code can cause any memory leak or delayed clean-up of the
generated classes and meta classes (as you mentioned in your last point)?

Thanks,
Aman

On Thu, Aug 10, 2017 at 5:53 AM, Jochen Theodorou <bl...@gmx.org> wrote:

> Just for reference...this seems to be https://stackoverflow.com/ques
> tions/45578426/lock-contention-in-groovy-shell-interpreter-under-high-load
>
> more inline
>
> On 09.08.2017 18:58, Aman Jain wrote:
>
>> Hello,
>>
>> We are evaluating GroovyShell <http://groovy-lang.org/download.html>
>> interpreter (v2.4) in our application for dynamically executing standard
>> Java syntax.
>>
>> Earlier, we were using Java BeanShell Interpreter for it, but it has an
>> issue <https://stackoverflow.com/questions/45450947/lock-contentio
>> n-in-java-beanshell-interpreter-under-high-load/45451768#45451768> under
>> high load which prompted us to look for an alternative such as Groovy.
>>
>> We are seeing thread lock contention when multiple threads execute the
>> below sample code simultaneously. We have multiple threads in the blocked
>> state which is degrading application performance.
>>
>
> I am missing the counter part, the one that owns the lock. but looking at
>
>     java.lang.Thread.State: BLOCKED (on object monitor)
>>     at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
>>         - waiting to lock <0x00000007bc425e40> (a java.lang.Object)
>>         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
>>         at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
>>
>
> my strong assumption would be, that the counter part is also in
> java.lang.ClassLoader. My guess would be, that we are currently trying to
> load a class, probably from some other thread. If you have code like
>
> static String script = "int y = x * x; System.out.println(\"** value of y
>> ** :: \" + y ); ";
>>
>> GroovyShell gs = new GroovyShell();
>> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
>> // bind variables
>> Binding binding = new Binding();
>> binding.setVariable("x", 5);
>> evalScript.setBinding(binding);
>> // invoke eval method
>> evalScript.invokeMethod("evalMethod", null);
>>
>
> you would with each thread execution do a new compilation, which is where
> the majority of those class look-ups is coming from. The script form
> example contains System, which will be looked-up in maybe 10 variants
> before the compiler is happy. That makes 9 false look-ups. Multiply this
> with a hundred threads and you get 900 look-ups for classes, that actually
> do not exist. So the goal would be reuse. My suggestion would be then:
>
> for all threads:
>
> static String script = "int y = x * x; System.out.println(\"** value of y
>> ** :: \" + y ); ";
>>
>> GroovyShell gs = new GroovyShell();
>> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
>>
>
> in each thread:
>
> // bind variables
> Binding binding = new Binding();
> binding.setVariable("x", 5);
> Script threadEvalScript = InvokerHelper.createScript(evalScript.getClas(),
> binding);
> // invoke eval method
> threadEvalScript.invokeMethod("evalMethod", null);
>
> Even better would be of course to make a pool of script instances and use
> them from there
>
>
> My questions are:
>>
>>  1. Has anyone experienced such problem? If yes, can you please suggest
>>     any possible resolution for it? I googled around for this problem
>>     and few blogs suggested to cache groovy |Script| object. Is
>>     |Script| object thread-safe? Moreover, I need to bind variables to
>>     |Script|object (via groovy |Binding| object, which is different for
>>     each execution in different threads), so I don't think caching
>>     groovy |Script| object is a viable option.
>>
>
> You have to understand that there is the script and the binding. Ideally
> the script itself stores all the state in the binding. Then you need one
> combination of script and binding per thread that is concurrently running.
> How you can do that I tried to show above already a bit.
>
> btw, Binding is not thread-safe, but nothing prevents you from
> implementing your own Binding, that is. But given your statement, that the
> Binding is different each time I do not think there is a problem with this.
>
>  2. Are there any best practices that I need to follow while using
>>     Groovy Shell interpreter with Java?
>>
>
> Biggest problem normally is the delayed clean-up of the generated classes
> and meta classes, but this should not concern you here, once you managed to
> reuse the script class.
>
> bye Jochen
>

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Jochen Theodorou <bl...@gmx.org>.
Just for reference...this seems to be 
https://stackoverflow.com/questions/45578426/lock-contention-in-groovy-shell-interpreter-under-high-load

more inline

On 09.08.2017 18:58, Aman Jain wrote:
> Hello,
> 
> We are evaluating GroovyShell 
> <http://groovy-lang.org/download.html> interpreter (v2.4) in our 
> application for dynamically executing standard Java syntax.
> 
> Earlier, we were using Java BeanShell Interpreter for it, but it has an 
> issue 
> <https://stackoverflow.com/questions/45450947/lock-contention-in-java-beanshell-interpreter-under-high-load/45451768#45451768> under 
> high load which prompted us to look for an alternative such as Groovy.
> 
> We are seeing thread lock contention when multiple threads execute the 
> below sample code simultaneously. We have multiple threads in the 
> blocked state which is degrading application performance.

I am missing the counter part, the one that owns the lock. but looking at

>     java.lang.Thread.State: BLOCKED (on object monitor)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
> 	- waiting to lock <0x00000007bc425e40> (a java.lang.Object)
> 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
> 	at java.lang.ClassLoader.loadClass(ClassLoader.java:411)

my strong assumption would be, that the counter part is also in 
java.lang.ClassLoader. My guess would be, that we are currently trying 
to load a class, probably from some other thread. If you have code like

> static String script = "int y = x * x; System.out.println(\"** value of y ** :: \" + y ); ";
> 
> GroovyShell gs = new GroovyShell();
> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
> // bind variables
> Binding binding = new Binding();
> binding.setVariable("x", 5);
> evalScript.setBinding(binding);
> // invoke eval method
> evalScript.invokeMethod("evalMethod", null);

you would with each thread execution do a new compilation, which is 
where the majority of those class look-ups is coming from. The script 
form example contains System, which will be looked-up in maybe 10 
variants before the compiler is happy. That makes 9 false look-ups. 
Multiply this with a hundred threads and you get 900 look-ups for 
classes, that actually do not exist. So the goal would be reuse. My 
suggestion would be then:

for all threads:

> static String script = "int y = x * x; System.out.println(\"** value of y ** :: \" + y ); ";
> 
> GroovyShell gs = new GroovyShell();
> Script evalScript = gs.parse("void evalMethod() {" + script + "}");

in each thread:

// bind variables
Binding binding = new Binding();
binding.setVariable("x", 5);
Script threadEvalScript = 
InvokerHelper.createScript(evalScript.getClas(), binding);
// invoke eval method
threadEvalScript.invokeMethod("evalMethod", null);

Even better would be of course to make a pool of script instances and 
use them from there


> My questions are:
> 
>  1. Has anyone experienced such problem? If yes, can you please suggest
>     any possible resolution for it? I googled around for this problem
>     and few blogs suggested to cache groovy |Script| object. Is
>     |Script| object thread-safe? Moreover, I need to bind variables to
>     |Script|object (via groovy |Binding| object, which is different for
>     each execution in different threads), so I don't think caching
>     groovy |Script| object is a viable option.

You have to understand that there is the script and the binding. Ideally 
the script itself stores all the state in the binding. Then you need one 
combination of script and binding per thread that is concurrently 
running. How you can do that I tried to show above already a bit.

btw, Binding is not thread-safe, but nothing prevents you from 
implementing your own Binding, that is. But given your statement, that 
the Binding is different each time I do not think there is a problem 
with this.

>  2. Are there any best practices that I need to follow while using
>     Groovy Shell interpreter with Java?

Biggest problem normally is the delayed clean-up of the generated 
classes and meta classes, but this should not concern you here, once you 
managed to reuse the script class.

bye Jochen

Re: Lock contention in Groovy Shell interpreter under high load

Posted by Jochen Theodorou <bl...@gmx.org>.
Just for reference...this seems to be 
https://stackoverflow.com/questions/45578426/lock-contention-in-groovy-shell-interpreter-under-high-load

more inline

On 09.08.2017 18:58, Aman Jain wrote:
> Hello,
> 
> We are evaluating GroovyShell 
> <http://groovy-lang.org/download.html> interpreter (v2.4) in our 
> application for dynamically executing standard Java syntax.
> 
> Earlier, we were using Java BeanShell Interpreter for it, but it has an 
> issue 
> <https://stackoverflow.com/questions/45450947/lock-contention-in-java-beanshell-interpreter-under-high-load/45451768#45451768> under 
> high load which prompted us to look for an alternative such as Groovy.
> 
> We are seeing thread lock contention when multiple threads execute the 
> below sample code simultaneously. We have multiple threads in the 
> blocked state which is degrading application performance.

I am missing the counter part, the one that owns the lock. but looking at

>     java.lang.Thread.State: BLOCKED (on object monitor)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
> 	- waiting to lock <0x00000007bc425e40> (a java.lang.Object)
> 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
> 	at java.lang.ClassLoader.loadClass(ClassLoader.java:411)

my strong assumption would be, that the counter part is also in 
java.lang.ClassLoader. My guess would be, that we are currently trying 
to load a class, probably from some other thread. If you have code like

> static String script = "int y = x * x; System.out.println(\"** value of y ** :: \" + y ); ";
> 
> GroovyShell gs = new GroovyShell();
> Script evalScript = gs.parse("void evalMethod() {" + script + "}");
> // bind variables
> Binding binding = new Binding();
> binding.setVariable("x", 5);
> evalScript.setBinding(binding);
> // invoke eval method
> evalScript.invokeMethod("evalMethod", null);

you would with each thread execution do a new compilation, which is 
where the majority of those class look-ups is coming from. The script 
form example contains System, which will be looked-up in maybe 10 
variants before the compiler is happy. That makes 9 false look-ups. 
Multiply this with a hundred threads and you get 900 look-ups for 
classes, that actually do not exist. So the goal would be reuse. My 
suggestion would be then:

for all threads:

> static String script = "int y = x * x; System.out.println(\"** value of y ** :: \" + y ); ";
> 
> GroovyShell gs = new GroovyShell();
> Script evalScript = gs.parse("void evalMethod() {" + script + "}");

in each thread:

// bind variables
Binding binding = new Binding();
binding.setVariable("x", 5);
Script threadEvalScript = 
InvokerHelper.createScript(evalScript.getClas(), binding);
// invoke eval method
threadEvalScript.invokeMethod("evalMethod", null);

Even better would be of course to make a pool of script instances and 
use them from there


> My questions are:
> 
>  1. Has anyone experienced such problem? If yes, can you please suggest
>     any possible resolution for it? I googled around for this problem
>     and few blogs suggested to cache groovy |Script| object. Is
>     |Script| object thread-safe? Moreover, I need to bind variables to
>     |Script|object (via groovy |Binding| object, which is different for
>     each execution in different threads), so I don't think caching
>     groovy |Script| object is a viable option.

You have to understand that there is the script and the binding. Ideally 
the script itself stores all the state in the binding. Then you need one 
combination of script and binding per thread that is concurrently 
running. How you can do that I tried to show above already a bit.

btw, Binding is not thread-safe, but nothing prevents you from 
implementing your own Binding, that is. But given your statement, that 
the Binding is different each time I do not think there is a problem 
with this.

>  2. Are there any best practices that I need to follow while using
>     Groovy Shell interpreter with Java?

Biggest problem normally is the delayed clean-up of the generated 
classes and meta classes, but this should not concern you here, once you 
managed to reuse the script class.

bye Jochen