The tracker was intended to be customized exactly as you did (I don't think I
have any bundle that uses the ST as is). Really do not believe the effort to
improve this is worth the effort though ... Especially since we're still
worrying about 1.4 which does not have the concurrent.util package.
Kind regards,
Peter Kriens
On 14 jan. 2014, at 17:40, Raymond Auge <[email protected]> wrote:
> 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é (@rotty3000)
>> Senior Software Architect
>> Liferay, Inc. (@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é (@rotty3000)
> Senior Software Architect
> Liferay, Inc. (@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