Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 341818 - [rosgi] System is out of thread resources when using r_osgi provider
Summary: [rosgi] System is out of thread resources when using r_osgi provider
Status: RESOLVED FIXED
Alias: None
Product: ECF
Classification: RT
Component: ecf.providers (show other bugs)
Version: 3.5.0   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 3.5.1   Edit
Assignee: Scott Lewis CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
Depends on:
Blocks:
 
Reported: 2011-04-04 12:18 EDT by ronen hamias CLA
Modified: 2011-05-11 10:48 EDT (History)
2 users (show)

See Also:


Attachments
zip file with source for rosgi RemoteServiceImpl class and supporting Activator class (4.12 KB, application/octet-stream)
2011-04-04 13:32 EDT, Scott Lewis CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description ronen hamias CLA 2011-04-04 12:18:56 EDT
Build Identifier: eclipse 3.6.2 SDK - ECF 3.5

executing the sample code:
org.eclipse.ecf.examples.remoteservices.hello.consumer.rs
org.eclipse.ecf.examples.remoteservices.hello.host.rs

the consumer code was enhanced:

        // 6. Finally...call the proxy

        long start, end, total;
        start = System.currentTimeMillis();
        String response=null;
       
        long count = 8000;
        for (int i = 0; i<count;i++)
              response = proxy.sayHello("RemoteService Consumer");

        end = System.currentTimeMillis();
        total = end - start;

        long avg = total/count;
        System.out.println("total=["+total+"][avg=" +(avg) +"]"+ response);

error recived:
An internal error has occurred.
unable to create new native thread


Reproducible: Always

Steps to Reproduce:
1. invoke the consumer 8000 times in close loop
2.
3.
Comment 1 ronen hamias CLA 2011-04-04 12:50:59 EDT
i have started to work on a patch.
 
i need to pass the thread pooling method and size to the container
what is the method to pass such configuration?
 
for example:
thread pooling method can be:
single thread
fixed size
...
 
poolSize is an int vlaue stating the pool size...
 
i am planing to use:
java.util.concurrent.Executors

 
best regards
ronen
Comment 2 Scott Lewis CLA 2011-04-04 13:20:07 EDT
Ronen,

I propose an approach different than what you have suggested.  Here's my proposal for dealing with this issue:

The rosgi provider currently uses an IExecutor instance to run both synchronous (callSync) and asynchronous (callAsync) remote method invocations.  For details, see:

org.eclipse.ecf.internal.provider.r_osgi.RemoteServiceImpl.callSync
and 
org.eclipse.ecf.internal.provider.r_osgi.RemoteServiceImpl.callAsync

IExecutor is an interface declared in the Equinox concurrent API...i.e. org.eclipse.equinox.concurrent bundle, org.eclipse.equinox.concurrent.future is the package where IExecutor lives.

Currently, the IExecutor instance for sync and async invocation is gotten by creating a new ThreadsExecutor for each and every sync (and async) invocation.  This is indeed wasteful, as ThreadsExecutor creates a new thread for every invocation (as you have discovered).  

Rather than build in a compile-time dependency on java5's concurrent API and the thread pooling that it supports...I would rather that the ECF remote service api...and the rosgi provider remain able to run on jre 1.4...instead I propose that we use the OSGI service registry to allow alternative IExecutor implementations to be read at call invoke time from the OSGi service registry...rather than creating a new ThreadsExecutor every time as we do now.  That way, people (like yourself...and others) could define *alternative* IExecutor implementations very easily, and simply register them as OSGi services...and then at call invoke time the r-osgi provider would look into the OSGi service registry, use any registered IExecutors...and if none are registered simply fall back to using the ThreadsExecutor as the default.

Note this would let you create an IExecutor based upon the java 1.5 concurrent API if you wish, and have *it* used rather than the ThreadsExecutor.  It would also allow people to use the JobsExecutor (based upon the Equinox jobs API...which also has thread pooling), the ImmediateExector (which uses the calling thread to execute IProgressRunnables immediately) or some other IExecutor implementation of their choosing.

For example, to register a new IExecutor for use in the rosgi provider for synchronous invocation, it would be a call like this:

Dictionary props = new Properties();
props.put("org.eclipse.ecf.provider.r_osgi.consumerExecutor","sync");
bundleContext.registerService(IExecutor.class.getName(),new MyExecutor(), props);

Then, in the rosgi provider code would be a call to lookup any synchronous IExecutors from the OSGi service registry...and use it...if any are defined with the property matching "org.eclipse.ecf.provider.r_osgi.consumerExecutor=sync".  If none are defined, then it would simply fall back to using the ThreadsExecutor.

I think this would be a much better way to generalize the rosgi provider, as it would then allow whatever alternative thread pooling mechanisms people wanted to use...without putting any compile time dependency on the concurrent API...and allowing a variety of already-implemented alternatives (JobsExecutor, ImmediateExecutor, ThreadsExecutor) to be reused (for example, the JobsExecutor already does thread pooling).

I've already implemented and tested this strategy for the rosgi provider, and will attach the source changes to this bug for examination in another posting.
Comment 3 Scott Lewis CLA 2011-04-04 13:23:05 EDT
Downgrading importance...I know it's important to you Ronen, and it will be addressed (possibly as soon as today), but it doesn't rise to the level of critical.
Comment 4 Scott Lewis CLA 2011-04-04 13:32:16 EDT
Created attachment 192485 [details]
zip file with source for rosgi RemoteServiceImpl class and supporting Activator class

This is a zip with the source code for the modified rosgi RemoteServiceImpl and supporting Activator class.  This implements the IExecutor OSGi service lookup strategy described in comment 2.

With approval, I will release this fix to master as soon as a couple of +1s appear.
Comment 5 Scott Lewis CLA 2011-04-04 13:47:53 EDT
Changing to new target milestone 3.5.1
Comment 6 Wim Jongman CLA 2011-04-05 07:05:19 EDT
(In reply to comment #2)

Yes, this is the way to go. +1 for Scott's approach.
Comment 7 ronen hamias CLA 2011-04-05 07:20:54 EDT
+1 for scott approach
i have also tested the patch and it fixed the problem
Comment 8 Scott Lewis CLA 2011-04-05 10:52:12 EDT
Ok...I've release the strategy outline in comment 2 to master.  

This fix requires some more documentation, however...i.e. to document the ability to register instances of IExecutor in order to customize the sync and async executors for the rosgi provider (by registering custom instances of IExecutor with the appropriate property value set).

Ronen...in return for this prompt fix, I would like to request that you contribute a wiki page addition to document this new aspect of the rosgi provider...with a simple example or two that shows it's usage.  Would you be willing to do this?  It would be most appreciated...and an excellent first contribution to the ECF community.  

One other thing...I think the documentation should include a warning of one side-effect introduced by this fix:  since the ImmediateExecutor is now used for synchronous rosgi invocation, it means that remote calls that block forever will *not* timeout.  Previously, since each synchronous invocation was invoked by a separate consumer-side thread, the remote call would timeout.  Now, with the ImmediateExecutor as the default, the invocation can potentially block forever.  I'm still sort of debating whether this should be the default, or if the ThreadsExecutor should be the default (as it was before this bug fix).  If ThreadsExecutor was the default, it would require Ronen (and others that were concerned about the scaling consequences of the ThreadsExecutor) to use the OSGi service mechanism described above to set to the sync executor to ImmediateExecutor.  In either case (the default is ImmediateExecutor or ThreadsExecutor) this should also be clearly documented by the wiki page.

Would this wiki page be something you would be willing to provide, Ronen?

I'll keep this bug open until we decide what to do WRT the documentation question.
Comment 9 ronen hamias CLA 2011-04-06 03:26:30 EDT
sure i will be happy to provide such wiki page
Comment 10 Scott Lewis CLA 2011-05-11 10:48:13 EDT
Resolving as fixed.  Ronen...would there be any chance that you could prepare a short wiki page describing this for ECF 3.5.1?  (We are planning release of 3.5.1 for May 19...i.e. prior to Indigo).