Number of simultaneous @Asynchronous threads

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Number of simultaneous @Asynchronous threads

Bjorn Danielsson
Hi guys,

Is there some way to configure the size of the thread pool used
for @Asynchronous execution of session bean methods? I can't get
more than 10 simultaneous threads executing @Asynchronous methods,
and I didn't find any obvious setting for this in tomee.xml or
service-jar.xml.

Version info:

apache-tomee-1.1.0-20120817.135055-110-plus

--
Björn Danielsson
Cuspy Code AB
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

David Blevins-2
Looks like we need to add a config property for it.  Easy change -- will
add it tomorrow unless Romain beats me to it (on my phone).

On Saturday, August 18, 2012, Bjorn Danielsson wrote:

> Hi guys,
>
> Is there some way to configure the size of the thread pool used
> for @Asynchronous execution of session bean methods? I can't get
> more than 10 simultaneous threads executing @Asynchronous methods,
> and I didn't find any obvious setting for this in tomee.xml or
> service-jar.xml.
>
> Version info:
>
> apache-tomee-1.1.0-20120817.135055-110-plus
>
> --
> Björn Danielsson
> Cuspy Code AB
>


--
Sent from my iPhone
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
weird it was 10, by defaukt we were between 10 and 20...

btw here is the new config(s):
https://issues.apache.org/jira/browse/TOMEE-382

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/19 David Blevins <[hidden email]>

> Looks like we need to add a config property for it.  Easy change -- will
> add it tomorrow unless Romain beats me to it (on my phone).
>
> On Saturday, August 18, 2012, Bjorn Danielsson wrote:
>
> > Hi guys,
> >
> > Is there some way to configure the size of the thread pool used
> > for @Asynchronous execution of session bean methods? I can't get
> > more than 10 simultaneous threads executing @Asynchronous methods,
> > and I didn't find any obvious setting for this in tomee.xml or
> > service-jar.xml.
> >
> > Version info:
> >
> > apache-tomee-1.1.0-20120817.135055-110-plus
> >
> > --
> > Björn Danielsson
> > Cuspy Code AB
> >
>
>
> --
> Sent from my iPhone
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

zeeman
Great, thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
FYI, with last David refactoring the config is a bit different from the one
i did, just to keep a track in this thread (jira is up to date), properties
are and can be put in application.properties (META-INF or WEB-INF):

AsynchronousPool.CorePoolSize
AsynchronousPool.MaximumPoolSize
AsynchronousPool.KeepAliveTime

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/20 zeeman <[hidden email]>

> Great, thanks.
>
>
>
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Bjorn Danielsson
I built from the latest source (r1374989) and tried the new
configuration, but I get strange errors. Just by placing the
default values in system.properties in a freshly unpacked
TomEE-plus, I got this exception:

INFO: Assembling app: openejb
Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
INFO: Using 'AsynchronousPool.CorePoolSize=10'
Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
INFO: Using 'AsynchronousPool.KeepAliveTime=60'
Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler destroyApplication
INFO: Undeploying app: openejb
Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler buildContainerSystem
SEVERE: Application could not be deployed:  openejb
org.apache.openejb.OpenEJBException: Creating application failed: openejb: null
        at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
        at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
        at org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
        at org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
        at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
        at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
        at org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
        at org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
        at org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: java.lang.NullPointerException
        at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
        at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
        at org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
        at org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
        at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
        ... 20 more

I also tried deploying my webapp and moved the properties to
WEB-INF/application.properties, and that produced a similar
exception with the same cause, but for my app instead of openejb
and with some differences in the lifecycle call chain.

--
Björn Danielsson
Cuspy Code AB


Romain Manni-Bucau <[hidden email]> wrote:

> FYI, with last David refactoring the config is a bit different from the one
> i did, just to keep a track in this thread (jira is up to date), properties
> are and can be put in application.properties (META-INF or WEB-INF):
>
> AsynchronousPool.CorePoolSize
> AsynchronousPool.MaximumPoolSize
> AsynchronousPool.KeepAliveTime
>
> *Romain Manni-Bucau*
> *Twitter: @rmannibucau*
> *Blog: http://rmannibucau.wordpress.com*
>
>
>
>
> 2012/8/20 zeeman <[hidden email]>
>
>> Great, thanks.
>>
>>
>>
>> --
>> View this message in context:
>> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
>> Sent from the OpenEJB User mailing list archive at Nabble.com.
>>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
i don't manage to reproduce it,

i simply put in conf/system.properties:

AsynchronousPool.CorePoolSize = 50
AsynchronousPool.MaximumPoolSize = 100


and in the log i get:

INFO: Using 'AsynchronousPool.CorePoolSize=50'
20 août 2012 16:21:40 org.apache.openejb.util.OptionsLog info
INFO: Using 'AsynchronousPool.MaximumPoolSize=100'

and no exception,

maybe you are not completely up to date?

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/20 Bjorn Danielsson <[hidden email]>

> I built from the latest source (r1374989) and tried the new
> configuration, but I get strange errors. Just by placing the
> default values in system.properties in a freshly unpacked
> TomEE-plus, I got this exception:
>
> INFO: Assembling app: openejb
> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> INFO: Using 'AsynchronousPool.CorePoolSize=10'
> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> INFO: Using 'AsynchronousPool.KeepAliveTime=60'
> Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler
> destroyApplication
> INFO: Undeploying app: openejb
> Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler
> buildContainerSystem
> SEVERE: Application could not be deployed:  openejb
> org.apache.openejb.OpenEJBException: Creating application failed: openejb:
> null
>         at
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
>         at
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
>         at
> org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
>         at
> org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
>         at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
>         at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
>         at
> org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
>         at
> org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
>         at
> org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
>         at
> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
>         at
> org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
>         at
> org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
>         at
> org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
>         at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
>         at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>         at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>         at java.lang.reflect.Method.invoke(Method.java:601)
>         at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
>         at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
> Caused by: java.lang.NullPointerException
>         at
> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
>         at
> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
>         at
> org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
>         at
> org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
>         at
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
>         ... 20 more
>
> I also tried deploying my webapp and moved the properties to
> WEB-INF/application.properties, and that produced a similar
> exception with the same cause, but for my app instead of openejb
> and with some differences in the lifecycle call chain.
>
> --
> Björn Danielsson
> Cuspy Code AB
>
>
> Romain Manni-Bucau <[hidden email]> wrote:
> > FYI, with last David refactoring the config is a bit different from the
> one
> > i did, just to keep a track in this thread (jira is up to date),
> properties
> > are and can be put in application.properties (META-INF or WEB-INF):
> >
> > AsynchronousPool.CorePoolSize
> > AsynchronousPool.MaximumPoolSize
> > AsynchronousPool.KeepAliveTime
> >
> > *Romain Manni-Bucau*
> > *Twitter: @rmannibucau*
> > *Blog: http://rmannibucau.wordpress.com*
> >
> >
> >
> >
> > 2012/8/20 zeeman <[hidden email]>
> >
> >> Great, thanks.
> >>
> >>
> >>
> >> --
> >> View this message in context:
> >>
> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
> >> Sent from the OpenEJB User mailing list archive at Nabble.com.
> >>
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Bjorn Danielsson
I found out that this setting is what causes the exception:

AsynchronousPool.KeepAliveTime = 60

Without it, everything is fine!

I simply added all three properties for testing, though I really
have no need to tweak KeepAliveTime. But just for the sake of
completeness: what's the intended format for that property?

Another strange thing that you mentioned earlier Romain, is
that in my tests the pool size never grows to MaximumPoolSize.
It always stays at CorePoolSize. I use test methods that sleep
for 10 seconds and log the timestamps and the Thread names,
and the results are consistent. I even tried spinning instead
of sleeping, but it made no difference.

--
Björn Danielsson
Cuspy Code AB


Romain Manni-Bucau <[hidden email]> wrote:

> i don't manage to reproduce it,
>
> i simply put in conf/system.properties:
>
> AsynchronousPool.CorePoolSize = 50
> AsynchronousPool.MaximumPoolSize = 100
>
>
> and in the log i get:
>
> INFO: Using 'AsynchronousPool.CorePoolSize=50'
> 20 août 2012 16:21:40 org.apache.openejb.util.OptionsLog info
> INFO: Using 'AsynchronousPool.MaximumPoolSize=100'
>
> and no exception,
>
> maybe you are not completely up to date?
>
> *Romain Manni-Bucau*
> *Twitter: @rmannibucau*
> *Blog: http://rmannibucau.wordpress.com*
>
>
>
>
> 2012/8/20 Bjorn Danielsson <[hidden email]>
>
>> I built from the latest source (r1374989) and tried the new
>> configuration, but I get strange errors. Just by placing the
>> default values in system.properties in a freshly unpacked
>> TomEE-plus, I got this exception:
>>
>> INFO: Assembling app: openejb
>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>> INFO: Using 'AsynchronousPool.CorePoolSize=10'
>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>> INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>> INFO: Using 'AsynchronousPool.KeepAliveTime=60'
>> Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler
>> destroyApplication
>> INFO: Undeploying app: openejb
>> Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler
>> buildContainerSystem
>> SEVERE: Application could not be deployed:  openejb
>> org.apache.openejb.OpenEJBException: Creating application failed: openejb:
>> null
>>         at
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
>>         at
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
>>         at
>> org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
>>         at
>> org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
>>         at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
>>         at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
>>         at
>> org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
>>         at
>> org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
>>         at
>> org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
>>         at
>> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
>>         at
>> org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
>>         at
>> org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
>>         at
>> org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
>>         at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
>>         at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>         at
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>         at
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>         at java.lang.reflect.Method.invoke(Method.java:601)
>>         at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
>>         at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
>> Caused by: java.lang.NullPointerException
>>         at
>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
>>         at
>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
>>         at
>> org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
>>         at
>> org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
>>         at
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
>>         ... 20 more
>>
>> I also tried deploying my webapp and moved the properties to
>> WEB-INF/application.properties, and that produced a similar
>> exception with the same cause, but for my app instead of openejb
>> and with some differences in the lifecycle call chain.
>>
>> --
>> Björn Danielsson
>> Cuspy Code AB
>>
>>
>> Romain Manni-Bucau <[hidden email]> wrote:
>> > FYI, with last David refactoring the config is a bit different from the
>> one
>> > i did, just to keep a track in this thread (jira is up to date),
>> properties
>> > are and can be put in application.properties (META-INF or WEB-INF):
>> >
>> > AsynchronousPool.CorePoolSize
>> > AsynchronousPool.MaximumPoolSize
>> > AsynchronousPool.KeepAliveTime
>> >
>> > *Romain Manni-Bucau*
>> > *Twitter: @rmannibucau*
>> > *Blog: http://rmannibucau.wordpress.com*
>> >
>> >
>> >
>> >
>> > 2012/8/20 zeeman <[hidden email]>
>> >
>> >> Great, thanks.
>> >>
>> >>
>> >>
>> >> --
>> >> View this message in context:
>> >>
>> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
>> >> Sent from the OpenEJB User mailing list archive at Nabble.com.
>> >>
>>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

David Blevins-2

On Aug 20, 2012, at 9:23 AM, Bjorn Danielsson wrote:

> I found out that this setting is what causes the exception:
>
> AsynchronousPool.KeepAliveTime = 60
>
> Without it, everything is fine!
>
> I simply added all three properties for testing, though I really
> have no need to tweak KeepAliveTime. But just for the sake of
> completeness: what's the intended format for that property?

Should be fixed now.  Forgot that the default TimeUnit needed to be supplied in code in case the user did not supply it.  The format looks like this:

 http://tomee.apache.org/configuring-durations.html

> Another strange thing that you mentioned earlier Romain, is
> that in my tests the pool size never grows to MaximumPoolSize.
> It always stays at CorePoolSize. I use test methods that sleep
> for 10 seconds and log the timestamps and the Thread names,
> and the results are consistent. I even tried spinning instead
> of sleeping, but it made no difference.

I've noticed that too in the past.  These arguments go straight into this object:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

The section on "Core and maximum pool sizes" seems to imply that it can grow and shrink, however, I've only ever noticed fixed pool size behavior.


-David

> Romain Manni-Bucau <[hidden email]> wrote:
>> i don't manage to reproduce it,
>>
>> i simply put in conf/system.properties:
>>
>> AsynchronousPool.CorePoolSize = 50
>> AsynchronousPool.MaximumPoolSize = 100
>>
>>
>> and in the log i get:
>>
>> INFO: Using 'AsynchronousPool.CorePoolSize=50'
>> 20 août 2012 16:21:40 org.apache.openejb.util.OptionsLog info
>> INFO: Using 'AsynchronousPool.MaximumPoolSize=100'
>>
>> and no exception,
>>
>> maybe you are not completely up to date?
>>
>> *Romain Manni-Bucau*
>> *Twitter: @rmannibucau*
>> *Blog: http://rmannibucau.wordpress.com*
>>
>>
>>
>>
>> 2012/8/20 Bjorn Danielsson <[hidden email]>
>>
>>> I built from the latest source (r1374989) and tried the new
>>> configuration, but I get strange errors. Just by placing the
>>> default values in system.properties in a freshly unpacked
>>> TomEE-plus, I got this exception:
>>>
>>> INFO: Assembling app: openejb
>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>> INFO: Using 'AsynchronousPool.CorePoolSize=10'
>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>> INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>> INFO: Using 'AsynchronousPool.KeepAliveTime=60'
>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler
>>> destroyApplication
>>> INFO: Undeploying app: openejb
>>> Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler
>>> buildContainerSystem
>>> SEVERE: Application could not be deployed:  openejb
>>> org.apache.openejb.OpenEJBException: Creating application failed: openejb:
>>> null
>>>        at
>>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
>>>        at
>>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
>>>        at
>>> org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
>>>        at
>>> org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
>>>        at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
>>>        at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
>>>        at
>>> org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
>>>        at
>>> org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
>>>        at
>>> org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
>>>        at
>>> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
>>>        at
>>> org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
>>>        at
>>> org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
>>>        at
>>> org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
>>>        at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
>>>        at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
>>>        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>        at
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>>        at
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>        at java.lang.reflect.Method.invoke(Method.java:601)
>>>        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
>>>        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
>>> Caused by: java.lang.NullPointerException
>>>        at
>>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
>>>        at
>>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
>>>        at
>>> org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
>>>        at
>>> org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
>>>        at
>>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
>>>        ... 20 more
>>>
>>> I also tried deploying my webapp and moved the properties to
>>> WEB-INF/application.properties, and that produced a similar
>>> exception with the same cause, but for my app instead of openejb
>>> and with some differences in the lifecycle call chain.
>>>
>>> --
>>> Björn Danielsson
>>> Cuspy Code AB
>>>
>>>
>>> Romain Manni-Bucau <[hidden email]> wrote:
>>>> FYI, with last David refactoring the config is a bit different from the
>>> one
>>>> i did, just to keep a track in this thread (jira is up to date),
>>> properties
>>>> are and can be put in application.properties (META-INF or WEB-INF):
>>>>
>>>> AsynchronousPool.CorePoolSize
>>>> AsynchronousPool.MaximumPoolSize
>>>> AsynchronousPool.KeepAliveTime
>>>>
>>>> *Romain Manni-Bucau*
>>>> *Twitter: @rmannibucau*
>>>> *Blog: http://rmannibucau.wordpress.com*
>>>>
>>>>
>>>>
>>>>
>>>> 2012/8/20 zeeman <[hidden email]>
>>>>
>>>>> Great, thanks.
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> View this message in context:
>>>>>
>>> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
>>>>> Sent from the OpenEJB User mailing list archive at Nabble.com.
>>>>>
>>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
that's because we use a linked blocking queue

maybe we should make it configurable, not sure...

wdyt?

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/20 David Blevins <[hidden email]>

>
> On Aug 20, 2012, at 9:23 AM, Bjorn Danielsson wrote:
>
> > I found out that this setting is what causes the exception:
> >
> > AsynchronousPool.KeepAliveTime = 60
> >
> > Without it, everything is fine!
> >
> > I simply added all three properties for testing, though I really
> > have no need to tweak KeepAliveTime. But just for the sake of
> > completeness: what's the intended format for that property?
>
> Should be fixed now.  Forgot that the default TimeUnit needed to be
> supplied in code in case the user did not supply it.  The format looks like
> this:
>
>  http://tomee.apache.org/configuring-durations.html
>
> > Another strange thing that you mentioned earlier Romain, is
> > that in my tests the pool size never grows to MaximumPoolSize.
> > It always stays at CorePoolSize. I use test methods that sleep
> > for 10 seconds and log the timestamps and the Thread names,
> > and the results are consistent. I even tried spinning instead
> > of sleeping, but it made no difference.
>
> I've noticed that too in the past.  These arguments go straight into this
> object:
>
>
> http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
>
> The section on "Core and maximum pool sizes" seems to imply that it can
> grow and shrink, however, I've only ever noticed fixed pool size behavior.
>
>
> -David
>
> > Romain Manni-Bucau <[hidden email]> wrote:
> >> i don't manage to reproduce it,
> >>
> >> i simply put in conf/system.properties:
> >>
> >> AsynchronousPool.CorePoolSize = 50
> >> AsynchronousPool.MaximumPoolSize = 100
> >>
> >>
> >> and in the log i get:
> >>
> >> INFO: Using 'AsynchronousPool.CorePoolSize=50'
> >> 20 août 2012 16:21:40 org.apache.openejb.util.OptionsLog info
> >> INFO: Using 'AsynchronousPool.MaximumPoolSize=100'
> >>
> >> and no exception,
> >>
> >> maybe you are not completely up to date?
> >>
> >> *Romain Manni-Bucau*
> >> *Twitter: @rmannibucau*
> >> *Blog: http://rmannibucau.wordpress.com*
> >>
> >>
> >>
> >>
> >> 2012/8/20 Bjorn Danielsson <[hidden email]>
> >>
> >>> I built from the latest source (r1374989) and tried the new
> >>> configuration, but I get strange errors. Just by placing the
> >>> default values in system.properties in a freshly unpacked
> >>> TomEE-plus, I got this exception:
> >>>
> >>> INFO: Assembling app: openejb
> >>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> >>> INFO: Using 'AsynchronousPool.CorePoolSize=10'
> >>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> >>> INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
> >>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
> >>> INFO: Using 'AsynchronousPool.KeepAliveTime=60'
> >>> Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler
> >>> destroyApplication
> >>> INFO: Undeploying app: openejb
> >>> Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler
> >>> buildContainerSystem
> >>> SEVERE: Application could not be deployed:  openejb
> >>> org.apache.openejb.OpenEJBException: Creating application failed:
> openejb:
> >>> null
> >>>        at
> >>>
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
> >>>        at
> >>>
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
> >>>        at
> >>>
> org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
> >>>        at
> >>>
> org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
> >>>        at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
> >>>        at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
> >>>        at
> >>>
> org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
> >>>        at
> >>> org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
> >>>        at
> >>>
> org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
> >>>        at
> >>>
> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
> >>>        at
> >>>
> org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
> >>>        at
> >>>
> org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
> >>>        at
> >>> org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
> >>>        at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
> >>>        at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
> >>>        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> >>>        at
> >>>
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> >>>        at
> >>>
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> >>>        at java.lang.reflect.Method.invoke(Method.java:601)
> >>>        at
> org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
> >>>        at
> org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
> >>> Caused by: java.lang.NullPointerException
> >>>        at
> >>>
> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
> >>>        at
> >>>
> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
> >>>        at
> >>>
> org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
> >>>        at
> >>>
> org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
> >>>        at
> >>>
> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
> >>>        ... 20 more
> >>>
> >>> I also tried deploying my webapp and moved the properties to
> >>> WEB-INF/application.properties, and that produced a similar
> >>> exception with the same cause, but for my app instead of openejb
> >>> and with some differences in the lifecycle call chain.
> >>>
> >>> --
> >>> Björn Danielsson
> >>> Cuspy Code AB
> >>>
> >>>
> >>> Romain Manni-Bucau <[hidden email]> wrote:
> >>>> FYI, with last David refactoring the config is a bit different from
> the
> >>> one
> >>>> i did, just to keep a track in this thread (jira is up to date),
> >>> properties
> >>>> are and can be put in application.properties (META-INF or WEB-INF):
> >>>>
> >>>> AsynchronousPool.CorePoolSize
> >>>> AsynchronousPool.MaximumPoolSize
> >>>> AsynchronousPool.KeepAliveTime
> >>>>
> >>>> *Romain Manni-Bucau*
> >>>> *Twitter: @rmannibucau*
> >>>> *Blog: http://rmannibucau.wordpress.com*
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> 2012/8/20 zeeman <[hidden email]>
> >>>>
> >>>>> Great, thanks.
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> View this message in context:
> >>>>>
> >>>
> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
> >>>>> Sent from the OpenEJB User mailing list archive at Nabble.com.
> >>>>>
> >>>
> >
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

David Blevins-2

On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:

> that's because we use a linked blocking queue
>
> maybe we should make it configurable, not sure...


Made it configurable.  Code is basically:

    public static AsynchronousPool create(AppContext appContext) {
        final Options options = appContext.getOptions();

        final String id = appContext.getId();
        final int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10);
        final int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
        final Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS));
        final BlockingQueue queue = options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);

        return new AsynchronousPool(id, corePoolSize, maximumPoolSize, keepAliveTime, queue);
    }

    private static enum QueueType {
        ARRAY,
        DELAY,
        LINKED,
        PRIORITY,
        SYNCHRONOUS;

        public BlockingQueue create(Options options) {
            switch (this) {
                case ARRAY: {
                    return new ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
                }
                case DELAY: {
                    return new DelayQueue();
                }
                case LINKED: {
                    return new LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", Integer.MAX_VALUE));
                }
                case PRIORITY: {
                    return new PriorityBlockingQueue();
                }
                case SYNCHRONOUS: {
                    return new SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
                }
                default: {
                    // The Options class will throw an error if the user supplies an unknown enum string
                    // The only way we can reach this is if we add a new QueueType element and forget to
                    // implement it in the above switch statement.
                    throw new IllegalArgumentException("Unknown QueueType type: " + this);
                }
            }
        }
    }




>
> 2012/8/20 David Blevins <[hidden email]>
>
>>
>> On Aug 20, 2012, at 9:23 AM, Bjorn Danielsson wrote:
>>
>>> I found out that this setting is what causes the exception:
>>>
>>> AsynchronousPool.KeepAliveTime = 60
>>>
>>> Without it, everything is fine!
>>>
>>> I simply added all three properties for testing, though I really
>>> have no need to tweak KeepAliveTime. But just for the sake of
>>> completeness: what's the intended format for that property?
>>
>> Should be fixed now.  Forgot that the default TimeUnit needed to be
>> supplied in code in case the user did not supply it.  The format looks like
>> this:
>>
>> http://tomee.apache.org/configuring-durations.html
>>
>>> Another strange thing that you mentioned earlier Romain, is
>>> that in my tests the pool size never grows to MaximumPoolSize.
>>> It always stays at CorePoolSize. I use test methods that sleep
>>> for 10 seconds and log the timestamps and the Thread names,
>>> and the results are consistent. I even tried spinning instead
>>> of sleeping, but it made no difference.
>>
>> I've noticed that too in the past.  These arguments go straight into this
>> object:
>>
>>
>> http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
>>
>> The section on "Core and maximum pool sizes" seems to imply that it can
>> grow and shrink, however, I've only ever noticed fixed pool size behavior.
>>
>>
>> -David
>>
>>> Romain Manni-Bucau <[hidden email]> wrote:
>>>> i don't manage to reproduce it,
>>>>
>>>> i simply put in conf/system.properties:
>>>>
>>>> AsynchronousPool.CorePoolSize = 50
>>>> AsynchronousPool.MaximumPoolSize = 100
>>>>
>>>>
>>>> and in the log i get:
>>>>
>>>> INFO: Using 'AsynchronousPool.CorePoolSize=50'
>>>> 20 août 2012 16:21:40 org.apache.openejb.util.OptionsLog info
>>>> INFO: Using 'AsynchronousPool.MaximumPoolSize=100'
>>>>
>>>> and no exception,
>>>>
>>>> maybe you are not completely up to date?
>>>>
>>>> *Romain Manni-Bucau*
>>>> *Twitter: @rmannibucau*
>>>> *Blog: http://rmannibucau.wordpress.com*
>>>>
>>>>
>>>>
>>>>
>>>> 2012/8/20 Bjorn Danielsson <[hidden email]>
>>>>
>>>>> I built from the latest source (r1374989) and tried the new
>>>>> configuration, but I get strange errors. Just by placing the
>>>>> default values in system.properties in a freshly unpacked
>>>>> TomEE-plus, I got this exception:
>>>>>
>>>>> INFO: Assembling app: openejb
>>>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>>>> INFO: Using 'AsynchronousPool.CorePoolSize=10'
>>>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>>>> INFO: Using 'AsynchronousPool.MaximumPoolSize=20'
>>>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.util.OptionsLog info
>>>>> INFO: Using 'AsynchronousPool.KeepAliveTime=60'
>>>>> Aug 20, 2012 3:56:28 PM org.apache.openejb.assembler.classic.Assembler
>>>>> destroyApplication
>>>>> INFO: Undeploying app: openejb
>>>>> Aug 20, 2012 3:56:29 PM org.apache.openejb.assembler.classic.Assembler
>>>>> buildContainerSystem
>>>>> SEVERE: Application could not be deployed:  openejb
>>>>> org.apache.openejb.OpenEJBException: Creating application failed:
>> openejb:
>>>>> null
>>>>>       at
>>>>>
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:929)
>>>>>       at
>>>>>
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:521)
>>>>>       at
>>>>>
>> org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:422)
>>>>>       at
>>>>>
>> org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:330)
>>>>>       at org.apache.openejb.OpenEJB$Instance.<init>(OpenEJB.java:144)
>>>>>       at org.apache.openejb.OpenEJB.init(OpenEJB.java:290)
>>>>>       at
>>>>>
>> org.apache.tomee.catalina.TomcatLoader.initialize(TomcatLoader.java:231)
>>>>>       at
>>>>> org.apache.tomee.catalina.TomcatLoader.init(TomcatLoader.java:131)
>>>>>       at
>>>>>
>> org.apache.tomee.catalina.ServerListener.lifecycleEvent(ServerListener.java:113)
>>>>>       at
>>>>>
>> org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
>>>>>       at
>>>>>
>> org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
>>>>>       at
>>>>>
>> org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401)
>>>>>       at
>>>>> org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110)
>>>>>       at org.apache.catalina.startup.Catalina.load(Catalina.java:624)
>>>>>       at org.apache.catalina.startup.Catalina.load(Catalina.java:649)
>>>>>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>>>       at
>>>>>
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>>>>       at
>>>>>
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>>>       at java.lang.reflect.Method.invoke(Method.java:601)
>>>>>       at
>> org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
>>>>>       at
>> org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
>>>>> Caused by: java.lang.NullPointerException
>>>>>       at
>>>>>
>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1281)
>>>>>       at
>>>>>
>> java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1198)
>>>>>       at
>>>>>
>> org.apache.openejb.async.AsynchronousPool.<init>(AsynchronousPool.java:51)
>>>>>       at
>>>>>
>> org.apache.openejb.async.AsynchronousPool.create(AsynchronousPool.java:66)
>>>>>       at
>>>>>
>> org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:589)
>>>>>       ... 20 more
>>>>>
>>>>> I also tried deploying my webapp and moved the properties to
>>>>> WEB-INF/application.properties, and that produced a similar
>>>>> exception with the same cause, but for my app instead of openejb
>>>>> and with some differences in the lifecycle call chain.
>>>>>
>>>>> --
>>>>> Björn Danielsson
>>>>> Cuspy Code AB
>>>>>
>>>>>
>>>>> Romain Manni-Bucau <[hidden email]> wrote:
>>>>>> FYI, with last David refactoring the config is a bit different from
>> the
>>>>> one
>>>>>> i did, just to keep a track in this thread (jira is up to date),
>>>>> properties
>>>>>> are and can be put in application.properties (META-INF or WEB-INF):
>>>>>>
>>>>>> AsynchronousPool.CorePoolSize
>>>>>> AsynchronousPool.MaximumPoolSize
>>>>>> AsynchronousPool.KeepAliveTime
>>>>>>
>>>>>> *Romain Manni-Bucau*
>>>>>> *Twitter: @rmannibucau*
>>>>>> *Blog: http://rmannibucau.wordpress.com*
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> 2012/8/20 zeeman <[hidden email]>
>>>>>>
>>>>>>> Great, thanks.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> View this message in context:
>>>>>>>
>>>>>
>> http://openejb.979440.n4.nabble.com/Number-of-simultaneous-Asynchronous-threads-tp4656891p4656908.html
>>>>>>> Sent from the OpenEJB User mailing list archive at Nabble.com.
>>>>>>>
>>>>>
>>>
>>
>>

Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Bjorn Danielsson
In my opinion this is a bit overkill, at least the options for
using DelayQueue and PriorityBlockingQueue. They require the
Runnable queue elements to implement the Delayed and Comparable
interfaces, respectively. I don't see how to make use of that in
an EJB method call.

I looked at the Sun ThreadPoolExecutor docs and have now played
a little with it in a standalone program. I honestly think the
design is a bit bizarre. I would expect the thread pool to expand
to max capacity before tasks are put in the wait queue. For the
purpose of optimizing CPU core utilization, the number of threads
in the operating system run-queue is the only important number,
not the number of provisioned threads in a JVM thread pool.
But this is slightly off-topic here.

I believe it's enough to have just one more configuration
property for TomEE: AsynchronousPool.QueueSize. If this is 0,
let the container use a SynchronousQueue. Otherwise use a
LinkedBlockingQueue with the specified capacity. That way it's
possible to have any of the three queueing strategies mentioned
in the ThreadPoolExecutor javadocs. I can't imagine a situation
where using an ArrayBlockingQueue instead of a bounded
LinkedBlockingQueue in TomEE really makes a big difference,
but I could be wrong about that.

--
Björn Danielsson
Cuspy Code AB


David Blevins <[hidden email]> wrote:

> On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
>
>> that's because we use a linked blocking queue
>>
>> maybe we should make it configurable, not sure...
>
>
> Made it configurable.  Code is basically:
>
>     public static AsynchronousPool create(AppContext appContext) {
>         final Options options = appContext.getOptions();
>
>         final String id = appContext.getId();
>         final int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10);
>         final int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
>         final Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS));
>         final BlockingQueue queue = options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
>
>         return new AsynchronousPool(id, corePoolSize, maximumPoolSize, keepAliveTime, queue);
>     }
>
>     private static enum QueueType {
>         ARRAY,
>         DELAY,
>         LINKED,
>         PRIORITY,
>         SYNCHRONOUS;
>
>         public BlockingQueue create(Options options) {
>             switch (this) {
>                 case ARRAY: {
>                     return new ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
>                 }
>                 case DELAY: {
>                     return new DelayQueue();
>                 }
>                 case LINKED: {
>                     return new LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", Integer.MAX_VALUE));
>                 }
>                 case PRIORITY: {
>                     return new PriorityBlockingQueue();
>                 }
>                 case SYNCHRONOUS: {
>                     return new SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
>                 }
>                 default: {
>                     // The Options class will throw an error if the user supplies an unknown enum string
>                     // The only way we can reach this is if we add a new QueueType element and forget to
>                     // implement it in the above switch statement.
>                     throw new IllegalArgumentException("Unknown QueueType type: " + this);
>                 }
>             }
>         }
>     }
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
hmm,

on the jvm implementation i personnaly think it is a good implementation
but the unbounded linkedblockingqueue case is not the one for which the
impl was designed IMO that's why it sounds strange i think.

about the conf i prefer to not switch to synchrous queue too easily since
it can blocks too much (could be a pity for sthg asynchronous ;)).

finally between array or linked case the main difference will be the array
case is less tolerant but i agree in an application well configured it
shouldn't make any difference.

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/21 Bjorn Danielsson <[hidden email]>

> In my opinion this is a bit overkill, at least the options for
> using DelayQueue and PriorityBlockingQueue. They require the
> Runnable queue elements to implement the Delayed and Comparable
> interfaces, respectively. I don't see how to make use of that in
> an EJB method call.
>
> I looked at the Sun ThreadPoolExecutor docs and have now played
> a little with it in a standalone program. I honestly think the
> design is a bit bizarre. I would expect the thread pool to expand
> to max capacity before tasks are put in the wait queue. For the
> purpose of optimizing CPU core utilization, the number of threads
> in the operating system run-queue is the only important number,
> not the number of provisioned threads in a JVM thread pool.
> But this is slightly off-topic here.
>
> I believe it's enough to have just one more configuration
> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
> let the container use a SynchronousQueue. Otherwise use a
> LinkedBlockingQueue with the specified capacity. That way it's
> possible to have any of the three queueing strategies mentioned
> in the ThreadPoolExecutor javadocs. I can't imagine a situation
> where using an ArrayBlockingQueue instead of a bounded
> LinkedBlockingQueue in TomEE really makes a big difference,
> but I could be wrong about that.
>
> --
> Björn Danielsson
> Cuspy Code AB
>
>
> David Blevins <[hidden email]> wrote:
> > On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
> >
> >> that's because we use a linked blocking queue
> >>
> >> maybe we should make it configurable, not sure...
> >
> >
> > Made it configurable.  Code is basically:
> >
> >     public static AsynchronousPool create(AppContext appContext) {
> >         final Options options = appContext.getOptions();
> >
> >         final String id = appContext.getId();
> >         final int corePoolSize =
> options.get("AsynchronousPool.CorePoolSize", 10);
> >         final int maximumPoolSize =
> Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
> >         final Duration keepAliveTime =
> options.get("AsynchronousPool.KeepAliveTime", new Duration(60,
> TimeUnit.SECONDS));
> >         final BlockingQueue queue =
> options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
> >
> >         return new AsynchronousPool(id, corePoolSize, maximumPoolSize,
> keepAliveTime, queue);
> >     }
> >
> >     private static enum QueueType {
> >         ARRAY,
> >         DELAY,
> >         LINKED,
> >         PRIORITY,
> >         SYNCHRONOUS;
> >
> >         public BlockingQueue create(Options options) {
> >             switch (this) {
> >                 case ARRAY: {
> >                     return new
> ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
> >                 }
> >                 case DELAY: {
> >                     return new DelayQueue();
> >                 }
> >                 case LINKED: {
> >                     return new
> LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize",
> Integer.MAX_VALUE));
> >                 }
> >                 case PRIORITY: {
> >                     return new PriorityBlockingQueue();
> >                 }
> >                 case SYNCHRONOUS: {
> >                     return new
> SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
> >                 }
> >                 default: {
> >                     // The Options class will throw an error if the user
> supplies an unknown enum string
> >                     // The only way we can reach this is if we add a new
> QueueType element and forget to
> >                     // implement it in the above switch statement.
> >                     throw new IllegalArgumentException("Unknown
> QueueType type: " + this);
> >                 }
> >             }
> >         }
> >     }
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Bjorn Danielsson
Can you give an example when a SynchronousQueue would block
too much? In my tests it works exactly like I would expect a
bounded queue with a size of zero to behave. The thread pool
reaches MaximumPoolSize and then a RejectedExecutionException
is thrown. For a LinkedBlockingQueue with size 1, exactly the
same thing happens but one submission later, since one element
was queued before the thread pool started to expand.

For the array vs bounded linked queue, I can't see how there
are any practical differences for a ThreadPoolExecutor except
for how memory is used to store the Runnable pointers in the
queue.

--
Björn Danielsson
Cuspy Code AB


Romain Manni-Bucau <[hidden email]> wrote:

> hmm,
>
> on the jvm implementation i personnaly think it is a good implementation
> but the unbounded linkedblockingqueue case is not the one for which the
> impl was designed IMO that's why it sounds strange i think.
>
> about the conf i prefer to not switch to synchrous queue too easily since
> it can blocks too much (could be a pity for sthg asynchronous ;)).
>
> finally between array or linked case the main difference will be the array
> case is less tolerant but i agree in an application well configured it
> shouldn't make any difference.
>
> *Romain Manni-Bucau*
> *Twitter: @rmannibucau*
> *Blog: http://rmannibucau.wordpress.com*
>
>
>
>
> 2012/8/21 Bjorn Danielsson <[hidden email]>
>
>> In my opinion this is a bit overkill, at least the options for
>> using DelayQueue and PriorityBlockingQueue. They require the
>> Runnable queue elements to implement the Delayed and Comparable
>> interfaces, respectively. I don't see how to make use of that in
>> an EJB method call.
>>
>> I looked at the Sun ThreadPoolExecutor docs and have now played
>> a little with it in a standalone program. I honestly think the
>> design is a bit bizarre. I would expect the thread pool to expand
>> to max capacity before tasks are put in the wait queue. For the
>> purpose of optimizing CPU core utilization, the number of threads
>> in the operating system run-queue is the only important number,
>> not the number of provisioned threads in a JVM thread pool.
>> But this is slightly off-topic here.
>>
>> I believe it's enough to have just one more configuration
>> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
>> let the container use a SynchronousQueue. Otherwise use a
>> LinkedBlockingQueue with the specified capacity. That way it's
>> possible to have any of the three queueing strategies mentioned
>> in the ThreadPoolExecutor javadocs. I can't imagine a situation
>> where using an ArrayBlockingQueue instead of a bounded
>> LinkedBlockingQueue in TomEE really makes a big difference,
>> but I could be wrong about that.
>>
>> --
>> Björn Danielsson
>> Cuspy Code AB
>>
>>
>> David Blevins <[hidden email]> wrote:
>> > On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
>> >
>> >> that's because we use a linked blocking queue
>> >>
>> >> maybe we should make it configurable, not sure...
>> >
>> >
>> > Made it configurable.  Code is basically:
>> >
>> >     public static AsynchronousPool create(AppContext appContext) {
>> >         final Options options = appContext.getOptions();
>> >
>> >         final String id = appContext.getId();
>> >         final int corePoolSize =
>> options.get("AsynchronousPool.CorePoolSize", 10);
>> >         final int maximumPoolSize =
>> Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
>> >         final Duration keepAliveTime =
>> options.get("AsynchronousPool.KeepAliveTime", new Duration(60,
>> TimeUnit.SECONDS));
>> >         final BlockingQueue queue =
>> options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
>> >
>> >         return new AsynchronousPool(id, corePoolSize, maximumPoolSize,
>> keepAliveTime, queue);
>> >     }
>> >
>> >     private static enum QueueType {
>> >         ARRAY,
>> >         DELAY,
>> >         LINKED,
>> >         PRIORITY,
>> >         SYNCHRONOUS;
>> >
>> >         public BlockingQueue create(Options options) {
>> >             switch (this) {
>> >                 case ARRAY: {
>> >                     return new
>> ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
>> >                 }
>> >                 case DELAY: {
>> >                     return new DelayQueue();
>> >                 }
>> >                 case LINKED: {
>> >                     return new
>> LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize",
>> Integer.MAX_VALUE));
>> >                 }
>> >                 case PRIORITY: {
>> >                     return new PriorityBlockingQueue();
>> >                 }
>> >                 case SYNCHRONOUS: {
>> >                     return new
>> SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
>> >                 }
>> >                 default: {
>> >                     // The Options class will throw an error if the user
>> supplies an unknown enum string
>> >                     // The only way we can reach this is if we add a new
>> QueueType element and forget to
>> >                     // implement it in the above switch statement.
>> >                     throw new IllegalArgumentException("Unknown
>> QueueType type: " + this);
>> >                 }
>> >             }
>> >         }
>> >     }
>>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Romain Manni-Bucau
yeah it works as expected but it is not what we (often) want, typically
RejectedExecutionException are an issue

in fact that's the only difference between all cases: when
will RejectedExecutionException be thrown

the linked case is the one avoiding it the more (but using more memory)..

solution are always a compromise ;)

*Romain Manni-Bucau*
*Twitter: @rmannibucau*
*Blog: http://rmannibucau.wordpress.com*




2012/8/21 Bjorn Danielsson <[hidden email]>

> Can you give an example when a SynchronousQueue would block
> too much? In my tests it works exactly like I would expect a
> bounded queue with a size of zero to behave. The thread pool
> reaches MaximumPoolSize and then a RejectedExecutionException
> is thrown. For a LinkedBlockingQueue with size 1, exactly the
> same thing happens but one submission later, since one element
> was queued before the thread pool started to expand.
>
> For the array vs bounded linked queue, I can't see how there
> are any practical differences for a ThreadPoolExecutor except
> for how memory is used to store the Runnable pointers in the
> queue.
>
> --
> Björn Danielsson
> Cuspy Code AB
>
>
> Romain Manni-Bucau <[hidden email]> wrote:
> > hmm,
> >
> > on the jvm implementation i personnaly think it is a good implementation
> > but the unbounded linkedblockingqueue case is not the one for which the
> > impl was designed IMO that's why it sounds strange i think.
> >
> > about the conf i prefer to not switch to synchrous queue too easily since
> > it can blocks too much (could be a pity for sthg asynchronous ;)).
> >
> > finally between array or linked case the main difference will be the
> array
> > case is less tolerant but i agree in an application well configured it
> > shouldn't make any difference.
> >
> > *Romain Manni-Bucau*
> > *Twitter: @rmannibucau*
> > *Blog: http://rmannibucau.wordpress.com*
> >
> >
> >
> >
> > 2012/8/21 Bjorn Danielsson <[hidden email]>
> >
> >> In my opinion this is a bit overkill, at least the options for
> >> using DelayQueue and PriorityBlockingQueue. They require the
> >> Runnable queue elements to implement the Delayed and Comparable
> >> interfaces, respectively. I don't see how to make use of that in
> >> an EJB method call.
> >>
> >> I looked at the Sun ThreadPoolExecutor docs and have now played
> >> a little with it in a standalone program. I honestly think the
> >> design is a bit bizarre. I would expect the thread pool to expand
> >> to max capacity before tasks are put in the wait queue. For the
> >> purpose of optimizing CPU core utilization, the number of threads
> >> in the operating system run-queue is the only important number,
> >> not the number of provisioned threads in a JVM thread pool.
> >> But this is slightly off-topic here.
> >>
> >> I believe it's enough to have just one more configuration
> >> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
> >> let the container use a SynchronousQueue. Otherwise use a
> >> LinkedBlockingQueue with the specified capacity. That way it's
> >> possible to have any of the three queueing strategies mentioned
> >> in the ThreadPoolExecutor javadocs. I can't imagine a situation
> >> where using an ArrayBlockingQueue instead of a bounded
> >> LinkedBlockingQueue in TomEE really makes a big difference,
> >> but I could be wrong about that.
> >>
> >> --
> >> Björn Danielsson
> >> Cuspy Code AB
> >>
> >>
> >> David Blevins <[hidden email]> wrote:
> >> > On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
> >> >
> >> >> that's because we use a linked blocking queue
> >> >>
> >> >> maybe we should make it configurable, not sure...
> >> >
> >> >
> >> > Made it configurable.  Code is basically:
> >> >
> >> >     public static AsynchronousPool create(AppContext appContext) {
> >> >         final Options options = appContext.getOptions();
> >> >
> >> >         final String id = appContext.getId();
> >> >         final int corePoolSize =
> >> options.get("AsynchronousPool.CorePoolSize", 10);
> >> >         final int maximumPoolSize =
> >> Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20),
> corePoolSize);
> >> >         final Duration keepAliveTime =
> >> options.get("AsynchronousPool.KeepAliveTime", new Duration(60,
> >> TimeUnit.SECONDS));
> >> >         final BlockingQueue queue =
> >> options.get("AsynchronousPool.QueueType",
> QueueType.LINKED).create(options);
> >> >
> >> >         return new AsynchronousPool(id, corePoolSize, maximumPoolSize,
> >> keepAliveTime, queue);
> >> >     }
> >> >
> >> >     private static enum QueueType {
> >> >         ARRAY,
> >> >         DELAY,
> >> >         LINKED,
> >> >         PRIORITY,
> >> >         SYNCHRONOUS;
> >> >
> >> >         public BlockingQueue create(Options options) {
> >> >             switch (this) {
> >> >                 case ARRAY: {
> >> >                     return new
> >> ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
> >> >                 }
> >> >                 case DELAY: {
> >> >                     return new DelayQueue();
> >> >                 }
> >> >                 case LINKED: {
> >> >                     return new
> >> LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize",
> >> Integer.MAX_VALUE));
> >> >                 }
> >> >                 case PRIORITY: {
> >> >                     return new PriorityBlockingQueue();
> >> >                 }
> >> >                 case SYNCHRONOUS: {
> >> >                     return new
> >> SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
> >> >                 }
> >> >                 default: {
> >> >                     // The Options class will throw an error if the
> user
> >> supplies an unknown enum string
> >> >                     // The only way we can reach this is if we add a
> new
> >> QueueType element and forget to
> >> >                     // implement it in the above switch statement.
> >> >                     throw new IllegalArgumentException("Unknown
> >> QueueType type: " + this);
> >> >                 }
> >> >             }
> >> >         }
> >> >     }
> >>
>
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

David Blevins-2
In reply to this post by Bjorn Danielsson

On Aug 21, 2012, at 2:18 AM, Bjorn Danielsson wrote:

> In my opinion this is a bit overkill, at least the options for
> using DelayQueue and PriorityBlockingQueue. They require the
> Runnable queue elements to implement the Delayed and Comparable
> interfaces, respectively. I don't see how to make use of that in
> an EJB method call.

Agreed.  Though now my mind is wondering if we should tag the runnables with the number of retries and have them support higher priority retry.  That's not applicable to the @Asynchronous support, but is a feature of the @Timeout/EJB Timer stuff which uses an identical executor. (i'm reworking that code too to get everything as consistent as possible)

We might even be able to support a @Priority(0.5) annotation or something for @Asynchronous methods.  Could be interesting.

> I looked at the Sun ThreadPoolExecutor docs and have now played
> a little with it in a standalone program. I honestly think the
> design is a bit bizarre. I would expect the thread pool to expand
> to max capacity before tasks are put in the wait queue. For the
> purpose of optimizing CPU core utilization, the number of threads
> in the operating system run-queue is the only important number,
> not the number of provisioned threads in a JVM thread pool.
> But this is slightly off-topic here.
>
> I believe it's enough to have just one more configuration
> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
> let the container use a SynchronousQueue. Otherwise use a
> LinkedBlockingQueue with the specified capacity. That way it's
> possible to have any of the three queueing strategies mentioned
> in the ThreadPoolExecutor javadocs. I can't imagine a situation
> where using an ArrayBlockingQueue instead of a bounded
> LinkedBlockingQueue in TomEE really makes a big difference,
> but I could be wrong about that.

Hacking again, will repost and see what you think.  As mentioned above, also cleaning up the EJB Timer @Timeout execution queue and any others I can find.


-David

>
> David Blevins <[hidden email]> wrote:
>> On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
>>
>>> that's because we use a linked blocking queue
>>>
>>> maybe we should make it configurable, not sure...
>>
>>
>> Made it configurable.  Code is basically:
>>
>>    public static AsynchronousPool create(AppContext appContext) {
>>        final Options options = appContext.getOptions();
>>
>>        final String id = appContext.getId();
>>        final int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10);
>>        final int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
>>        final Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS));
>>        final BlockingQueue queue = options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
>>
>>        return new AsynchronousPool(id, corePoolSize, maximumPoolSize, keepAliveTime, queue);
>>    }
>>
>>    private static enum QueueType {
>>        ARRAY,
>>        DELAY,
>>        LINKED,
>>        PRIORITY,
>>        SYNCHRONOUS;
>>
>>        public BlockingQueue create(Options options) {
>>            switch (this) {
>>                case ARRAY: {
>>                    return new ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
>>                }
>>                case DELAY: {
>>                    return new DelayQueue();
>>                }
>>                case LINKED: {
>>                    return new LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", Integer.MAX_VALUE));
>>                }
>>                case PRIORITY: {
>>                    return new PriorityBlockingQueue();
>>                }
>>                case SYNCHRONOUS: {
>>                    return new SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
>>                }
>>                default: {
>>                    // The Options class will throw an error if the user supplies an unknown enum string
>>                    // The only way we can reach this is if we add a new QueueType element and forget to
>>                    // implement it in the above switch statement.
>>                    throw new IllegalArgumentException("Unknown QueueType type: " + this);
>>                }
>>            }
>>        }
>>    }

Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

Bjorn Danielsson
Great! I'll give it a try when you update. I use @Timeout also,
but I haven't been stress-testing that stuff as much yet.

According to the docs, PriorityBlockingQueue is always unbounded,
so at least one other queue type would be needed if bounded queues
are to be an option (making MaximumPoolSize meaningful).

--
Björn Danielsson
Cuspy Code AB


David Blevins <[hidden email]> wrote:

> On Aug 21, 2012, at 2:18 AM, Bjorn Danielsson wrote:
>
>> In my opinion this is a bit overkill, at least the options for
>> using DelayQueue and PriorityBlockingQueue. They require the
>> Runnable queue elements to implement the Delayed and Comparable
>> interfaces, respectively. I don't see how to make use of that in
>> an EJB method call.
>
> Agreed.  Though now my mind is wondering if we should tag the runnables with the number of retries and have them support higher priority retry.  That's not applicable to the @Asynchronous support, but is a feature of the @Timeout/EJB Timer stuff which uses an identical executor. (i'm reworking that code too to get everything as consistent as possible)
>
> We might even be able to support a @Priority(0.5) annotation or something for @Asynchronous methods.  Could be interesting.
>
>> I looked at the Sun ThreadPoolExecutor docs and have now played
>> a little with it in a standalone program. I honestly think the
>> design is a bit bizarre. I would expect the thread pool to expand
>> to max capacity before tasks are put in the wait queue. For the
>> purpose of optimizing CPU core utilization, the number of threads
>> in the operating system run-queue is the only important number,
>> not the number of provisioned threads in a JVM thread pool.
>> But this is slightly off-topic here.
>>
>> I believe it's enough to have just one more configuration
>> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
>> let the container use a SynchronousQueue. Otherwise use a
>> LinkedBlockingQueue with the specified capacity. That way it's
>> possible to have any of the three queueing strategies mentioned
>> in the ThreadPoolExecutor javadocs. I can't imagine a situation
>> where using an ArrayBlockingQueue instead of a bounded
>> LinkedBlockingQueue in TomEE really makes a big difference,
>> but I could be wrong about that.
>
> Hacking again, will repost and see what you think.  As mentioned above, also cleaning up the EJB Timer @Timeout execution queue and any others I can find.
>
>
> -David
>
>>
>> David Blevins <[hidden email]> wrote:
>>> On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
>>>
>>>> that's because we use a linked blocking queue
>>>>
>>>> maybe we should make it configurable, not sure...
>>>
>>>
>>> Made it configurable.  Code is basically:
>>>
>>>    public static AsynchronousPool create(AppContext appContext) {
>>>        final Options options = appContext.getOptions();
>>>
>>>        final String id = appContext.getId();
>>>        final int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10);
>>>        final int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
>>>        final Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS));
>>>        final BlockingQueue queue = options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
>>>
>>>        return new AsynchronousPool(id, corePoolSize, maximumPoolSize, keepAliveTime, queue);
>>>    }
>>>
>>>    private static enum QueueType {
>>>        ARRAY,
>>>        DELAY,
>>>        LINKED,
>>>        PRIORITY,
>>>        SYNCHRONOUS;
>>>
>>>        public BlockingQueue create(Options options) {
>>>            switch (this) {
>>>                case ARRAY: {
>>>                    return new ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
>>>                }
>>>                case DELAY: {
>>>                    return new DelayQueue();
>>>                }
>>>                case LINKED: {
>>>                    return new LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", Integer.MAX_VALUE));
>>>                }
>>>                case PRIORITY: {
>>>                    return new PriorityBlockingQueue();
>>>                }
>>>                case SYNCHRONOUS: {
>>>                    return new SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
>>>                }
>>>                default: {
>>>                    // The Options class will throw an error if the user supplies an unknown enum string
>>>                    // The only way we can reach this is if we add a new QueueType element and forget to
>>>                    // implement it in the above switch statement.
>>>                    throw new IllegalArgumentException("Unknown QueueType type: " + this);
>>>                }
>>>            }
>>>        }
>>>    }
Reply | Threaded
Open this post in threaded view
|

Re: Number of simultaneous @Asynchronous threads

David Blevins-2
In reply to this post by David Blevins-2

On Aug 21, 2012, at 11:27 AM, David Blevins wrote:

>
> On Aug 21, 2012, at 2:18 AM, Bjorn Danielsson wrote:
>
>> In my opinion this is a bit overkill, at least the options for
>> using DelayQueue and PriorityBlockingQueue. They require the
>> Runnable queue elements to implement the Delayed and Comparable
>> interfaces, respectively. I don't see how to make use of that in
>> an EJB method call.
>
> Agreed.  Though now my mind is wondering if we should tag the runnables with the number of retries and have them support higher priority retry.  That's not applicable to the @Asynchronous support, but is a feature of the @Timeout/EJB Timer stuff which uses an identical executor. (i'm reworking that code too to get everything as consistent as possible)
>
> We might even be able to support a @Priority(0.5) annotation or something for @Asynchronous methods.  Could be interesting.
>
>> I looked at the Sun ThreadPoolExecutor docs and have now played
>> a little with it in a standalone program. I honestly think the
>> design is a bit bizarre. I would expect the thread pool to expand
>> to max capacity before tasks are put in the wait queue. For the
>> purpose of optimizing CPU core utilization, the number of threads
>> in the operating system run-queue is the only important number,
>> not the number of provisioned threads in a JVM thread pool.
>> But this is slightly off-topic here.
>>
>> I believe it's enough to have just one more configuration
>> property for TomEE: AsynchronousPool.QueueSize. If this is 0,
>> let the container use a SynchronousQueue. Otherwise use a
>> LinkedBlockingQueue with the specified capacity. That way it's
>> possible to have any of the three queueing strategies mentioned
>> in the ThreadPoolExecutor javadocs. I can't imagine a situation
>> where using an ArrayBlockingQueue instead of a bounded
>> LinkedBlockingQueue in TomEE really makes a big difference,
>> but I could be wrong about that.
>
> Hacking again, will repost and see what you think.  As mentioned above, also cleaning up the EJB Timer @Timeout execution queue and any others I can find.

Work in progress, but here's an idea:

 https://gist.github.com/3418341

Can still yank ARRAY and PRIORITY, but the idea is to make the defaults as smart as possible based on what you have explicitly configured.

Some of the more interesting aspects:

AllowCoreThreadTimeOut=true essentially makes CorePoolSize and MaximumPoolSize the same thing in the regards that you have a thread pool size that can shrink.  Core and Maximum become really subjective at that point.  Probably you only need Core.

The idea behind the OfferRejectedExecutionHandler is to basically throttle the input to hopefully match the output.  I.e. slow down the people producing work to give the "doing" work side a chance to catch up.  Theoretically this is a much smarter queue.  Wether you're 100th in line to add to a Synchronous queue or 100th in line in a bounded queue, you're still 99 jobs away from getting your work done.  If you're actually waiting on a Future.get() then it should theoretically come out being the same.

The default queue size is really the one I am least certain about.

It would seem that with AllowCoreThreadTimeOut=true and CorePoolSize=20 and MaximumPoolSize=CorePoolSize the goal of QueueSize would be the tiniest buffer to ensure as close to 100% utilization as possible without letting the "work input" side get too much larger than the "work output" side.


-David

>> David Blevins <[hidden email]> wrote:
>>> On Aug 20, 2012, at 10:55 AM, Romain Manni-Bucau wrote:
>>>
>>>> that's because we use a linked blocking queue
>>>>
>>>> maybe we should make it configurable, not sure...
>>>
>>>
>>> Made it configurable.  Code is basically:
>>>
>>>   public static AsynchronousPool create(AppContext appContext) {
>>>       final Options options = appContext.getOptions();
>>>
>>>       final String id = appContext.getId();
>>>       final int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10);
>>>       final int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", 20), corePoolSize);
>>>       final Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS));
>>>       final BlockingQueue queue = options.get("AsynchronousPool.QueueType", QueueType.LINKED).create(options);
>>>
>>>       return new AsynchronousPool(id, corePoolSize, maximumPoolSize, keepAliveTime, queue);
>>>   }
>>>
>>>   private static enum QueueType {
>>>       ARRAY,
>>>       DELAY,
>>>       LINKED,
>>>       PRIORITY,
>>>       SYNCHRONOUS;
>>>
>>>       public BlockingQueue create(Options options) {
>>>           switch (this) {
>>>               case ARRAY: {
>>>                   return new ArrayBlockingQueue(options.get("AsynchronousPool.QueueSize", 100));
>>>               }
>>>               case DELAY: {
>>>                   return new DelayQueue();
>>>               }
>>>               case LINKED: {
>>>                   return new LinkedBlockingQueue(options.get("AsynchronousPool.QueueSize", Integer.MAX_VALUE));
>>>               }
>>>               case PRIORITY: {
>>>                   return new PriorityBlockingQueue();
>>>               }
>>>               case SYNCHRONOUS: {
>>>                   return new SynchronousQueue(options.get("AsynchronousPool.QueueFair", false));
>>>               }
>>>               default: {
>>>                   // The Options class will throw an error if the user supplies an unknown enum string
>>>                   // The only way we can reach this is if we add a new QueueType element and forget to
>>>                   // implement it in the above switch statement.
>>>                   throw new IllegalArgumentException("Unknown QueueType type: " + this);
>>>               }
>>>           }
>>>       }
>>>   }
>