Ok allow me to explain the use case because I think it's been lost.

I have the following pattern (very common in almost every system):

LifecycleEvent lifecycleEvent = ...

for (LifecycleAction lifecycleAction : handlers) {
lifecycleAction.processLifecycleEvent(lifecycleEvent);
}

Now, I would like the collection "handlers" to keep an updated list of
registered lifecycleActions which are registered as services.

The first approach you might consider is to simply do this:

LifecycleEvent lifecycleEvent = ...

for (Object service : _serviceTracker.getServices()) {
((LifecycleAction)service).processLifecycleEvent(lifecycleEvent);
}

However, the call to getServices contains a synchronized block which means
you've just serialized the entire application even though to the
unsuspecting developer doing so seemed highly plausible.

A slightly better approach is to use the tracked Map values directly:

LifecycleEvent lifecycleEvent = ...

for (LifecycleAction lifecycleAction :
_serviceTracker.getTracked().values()) {

lifecycleAction.processLifecycleEvent(lifecycleEvent);
}

This is a little better, since you still have a synchronized block around
the internal copy operation.

I think I realized that it's not a good idea to directly use the tracker.
In it's place I created a collection which wraps a tracker, and combines a
ServiceTrackerCustomizer and a CopyOnWriteArrayList holding the tracked
services that come through the customizer. I then use this collection in
place of the tracker:

BeanchmarkLifecycleEvent lifecycleEvent = ...

for (LifecycleAction lifecycleAction : _serviceTrackerCollection) {
lifecycleAction.processLifecycleEvent(lifecycleEvent);
}

This last is highly concurrent and still preserves the updates occurring to
the underlying collection because the iterators emitted by the
CopyOnWriteArray are thread safe and immutable.

This concept follows the principles described in Java Concurrency in
Practice:
- effective immutability
- safe publishing

My opinion is that the ServiceTracker itself could actually implement these
very same principles internally making them just as thread safe as they are
currently while also dramatically increasing their concurrency.

If you look at the tracker code now, if the tracked set of services was an
immutable copy of the actual tracked services, the only access to the
mutable collection would be from within
"update" code which could be synchronized. During this same synchronized
block the mutable collection could be copied to a volatile but immutable
reference which is then used everywhere for access. This would give you the
exact same safety while solving the concurrency issue.

That's all I'm saying!

Thx
- Ray


On Tue, Jan 14, 2014 at 4:06 AM, Peter Kriens <[email protected]>wrote:

> Any systems that is slowed down by ServiceTracker operations has other
> problems as well since the service registry was not intended to be used in
> a way that service events become a significant part of the CPU time. In
> general this means that service events are abused as event mechanisms since
> it is hard to see any other reasons why service events would overwhelm a
> system?
>
> This sounds like one of those things where you can get 200% improvement on
> the micro benchmark but don't see any noticeable difference in the whole?
>
> Kind regards,
>
> Peter Kriens
>
>
>
> On 9 jan. 2014, at 17:17, Raymond Auge <[email protected]> wrote:
>
> Recently I've performed some JMH benchmarking on the usecases for
> retireving collections of services.
>
> I discovered that raw usage of the ServiceTracker is in fact very slow for
> most cases due to heavy synchronization (both equinox and felix seem to
> have similar synchronization, although all my tests were actually against
> equinox).
>
> Has this ever been discussed or reviewed?
>
> It seems that since this is such a core function any improvement here
> would greatly affect/improve performance overall (not that it's really
> bad... except under significant concurrency).
>
> i.e. lock free impl.
>
> Thoughts?
>
> --
> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>  (@rotty3000)
> Senior Software Architect
> *Liferay, Inc.* <http://www.liferay.com/> (@Liferay)
>
>
>
>
>  _______________________________________________
> OSGi Developer Mail List
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>
>
>
> _______________________________________________
> OSGi Developer Mail List
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>



-- 
*Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
 (@rotty3000)
Senior Software Architect
*Liferay, Inc.* <http://www.liferay.com> (@Liferay)
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to