Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Equinox » service registry with many similar services
service registry with many similar services [message #635534] Wed, 27 October 2010 09:20 Go to next message
Lars Fischer is currently offline Lars FischerFriend
Messages: 105
Registered: July 2009
Senior Member
Hello,

I would like to create a system which provides functions with some
special requirements:
- the count of the functions could be very large (some thousands)
- multiple versions of one function have to be available at the same
time with the possibility to add a new version at any time
- dynamic calls to a function given the required name and version parameters

My plan was to use OSGi and provide the functions as services:
One "Function" interface with an "execute" method. All function classes
are implementing this interface. Every function instance would be
registered as OSGi service with a name and a version property. A call to
a function results in a search inside the service registry with the
given name and version as filter. On the found function service the
execute method will be called.

Now I created some simple tests to prove the feasibility with the result
that the performance looks quite bad to me:
- 1000 named functions, every function has 10 different versions
- as result there are 10 000 services registered inside the service registry
- The look-up directly calls BundleContext#getServiceReferences without
ServiceTrackers.
- Multi-threaded searches for a particular function are really slow. On
my standard machine I could execute only 15 searches per second. 5000
named functions with 10 versions are a pain...

I looked inside the ServiceRegistry#lookupServiceRegistrations. There is
an ArrayList containing all registered services for a named class (my
Function interface), which would be searched by the filter.

Is there a way to speed up the search?

Additional filter parameters will have no effect, because the services
still use the same class name.

Using different interfaces is no choice, because all functions are used
the same way.

Could the usage of one or multiple ServiceTrackers help me?

I would be very happy, if someone could give me a hint, how I can solve
my requirements using OSGi or speed up the search for the right service
instance.

Kind regards,
Lars
Re: service registry with many similar services [message #635565 is a reply to message #635534] Wed, 27 October 2010 10:38 Go to previous messageGo to next message
Lars Fischer is currently offline Lars FischerFriend
Messages: 105
Registered: July 2009
Senior Member
On 27.10.2010 11:20, Lars Fischer wrote:
>
> Is there a way to speed up the search?
>
> Could the usage of one or multiple ServiceTrackers help me?

I'm thinking about an own registry for my function services:

One place which gets informed, if a new function service will be
available or if a service has gone (whiteboard pattern ?).

This place will cache all services (I know this is bad OSGi style) and
could provide a faster search than using an OSGi filter. Maybe an unique
combination over a given parameter set.

Could this be a solution?

Kind regards,
Lars
Re: service registry with many similar services [message #635588 is a reply to message #635565] Wed, 27 October 2010 12:58 Go to previous messageGo to next message
BJ Hargrave is currently offline BJ HargraveFriend
Messages: 60
Registered: July 2009
Member
Well that is essentially what a ServiceTracker does. It is a local cache of services which meet some criteria.

You design with every service having the same objectClass name means the only way to discriminate among the services is with a Filter over the service properties. These filter evaluations is probably where the time is spent on the service lookup.

Using a set of ServiceTrackers will move the filter evaluation cost to the service registration time or ServiceTracker open time (which ever happens last). But it does mean that lookup from the tracker will be very quick since the filter evaluation has already been performed.
Re: service registry with many similar services [message #635590 is a reply to message #635588] Wed, 27 October 2010 13:07 Go to previous messageGo to next message
Thomas Watson is currently offline Thomas WatsonFriend
Messages: 503
Registered: July 2009
Senior Member
Another option is to use a single ServiceTracker with a customizer. Your customizer could be used to hash the services into a map which is keyed by some object representing the function name and version. Then you could lookup the service object in this map which is maintained by the ServiceTrackerCustomizer.
Re: service registry with many similar services [message #635647 is a reply to message #635590] Wed, 27 October 2010 15:20 Go to previous messageGo to next message
Lars Fischer is currently offline Lars FischerFriend
Messages: 105
Registered: July 2009
Senior Member
Hello Thomas,

On 27.10.2010 15:07, Thomas Watson wrote:
> Another option is to use a single ServiceTracker with a customizer.
> Your customizer could be used to hash the services into a map which is
> keyed by some object representing the function name and version. Then
> you could lookup the service object in this map which is maintained by
> the ServiceTrackerCustomizer.

Thank you for the suggestion.

Now I extend ServiceTracker and overwrite the Customizer methods to put
the given ServiceReferences in a ConcurrentHashMap with a calculated
unique key. With this key, the access to a service is much faster.


But I have some additional questions:

1) I store the ServiceReference in my map and always call something like

ServiceReference reference = cachedServiceReferences.get(key);
IService service = (IService) getService(reference);

Would it be a better solution to store the IService instances than the
ServiceReference to prevent the getService call and the cast?


2) How about concurrent access to a removed service? Is it guaranteed
that a service is available until the
ServiceTrackerCustomizer#removedService has finished? Or could the
service became unavailable before it is removed from my map?


Kind regards,
Lars
Re: service registry with many similar services [message #635648 is a reply to message #635588] Wed, 27 October 2010 15:30 Go to previous messageGo to next message
Lars Fischer is currently offline Lars FischerFriend
Messages: 105
Registered: July 2009
Senior Member
Hello BJ,

thank you very much for your answer!

On 27.10.2010 14:58, BJ Hargrave wrote:
> Well that is essentially what a ServiceTracker does. It is a local cache
> of services which meet some criteria.
> You design with every service having the same objectClass name means the
> only way to discriminate among the services is with a Filter over the
> service properties. These filter evaluations is probably where the time
> is spent on the service lookup.

Yes, the search with a filter consumes most of the time.


> Using a set of ServiceTrackers will move the filter evaluation cost to
> the service registration time or ServiceTracker open time (which ever
> happens last). But it does mean that lookup from the tracker will be
> very quick since the filter evaluation has already been performed.

Good to know.

Now I use one instance of my own ServiceTracker which uses only the
Service class name without a filter and the ServiceTrackerCustomizer
methods to cache _all_ services. A lookup returns a service from the
cached ServiceReference. This is working fast for the lookup.

Do you think this is a valid and safe solution? Do I have to keep track
of some traps when using cached ServiceReferences this way?

Kind regards,
Lars
Re: service registry with many similar services [message #636154 is a reply to message #635647] Fri, 29 October 2010 13:38 Go to previous message
Thomas Watson is currently offline Thomas WatsonFriend
Messages: 503
Registered: July 2009
Senior Member
Lars Fischer wrote on Wed, 27 October 2010 10:20

But I have some additional questions:

1) I store the ServiceReference in my map and always call something like

ServiceReference reference = cachedServiceReferences.get(key);
IService service = (IService) getService(reference);

Would it be a better solution to store the IService instances than the
ServiceReference to prevent the getService call and the cast?



I would use ServiceReference values as you are doing. Reason is in case the implementation uses a ServiceFactory. It is better to put off getting the service object until you actually need to call the method on it. This way the ServiceFactory can be lazy and not construct the object until needed by you.

Lars Fischer wrote on Wed, 27 October 2010 10:20

2) How about concurrent access to a removed service? Is it guaranteed
that a service is available until the
ServiceTrackerCustomizer#removedService has finished? Or could the
service became unavailable before it is removed from my map?

Kind regards,
Lars



First of all, your customizer must be thread safe. The methods on it can be called from any thread that is manipulating the registration of the services you are tracking. So access to your Map needs to be thread safe. I would also recommend that you do not hold any locks while you call getService(reference). You should always check if (IService) getService(reference); returns null. This can return null for a couple of reasons, 1) the service got unregistered before you could get it 2) a ServiceFactory had an error or decided not to return a service object for your bundle.

So bottom line, addingService, removingService should simply maintain your Map of key->ServiceReferences you are tracking. Also don't forget about modifiedService. You will have to find the value in your map for the modified service reference and rehash it with the potentially new function name and version key. I would not worry to much about performance since this case should be rare. If you think service registration will change function names or version on the fly without be unregistered and reregistered then you may have to consider using two maps to track key->service-reference and service-reference->key. This way you can quickly use the service-reference->key map to discover the key that is getting modified.

And then you use that map to discover a ServiceReference which has the proper function name and version you need and call getService(reference) to obtain the function implementation.

HTH

Tom

Previous Topic:Installing fix through classic update
Next Topic:Repository created by FeaturesAndBundlesPublisher doesn't show any items inside eclipse
Goto Forum:
  


Current Time: Sat Apr 20 06:27:45 GMT 2024

Powered by FUDForum. Page generated in 0.03081 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top