[
https://issues.apache.org/jira/browse/FELIX-5247?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15278855#comment-15278855
]
Thomas Watson commented on FELIX-5247:
--------------------------------------
The ResolverImpl can be constructed with an optional Executor that can control
the lifecycle of the threads used. In the Equinox framework I use this
constructor so I can have my own executor that manages the pool of threads.
Equinox also registers the Resolver service with a ResolverImpl that uses a
synchronous (single threaded) executor. That effectively makes the Resolver
service single threaded.
I'm still not convinced the work the resolver does in parallel is buy us much
in terms of resolver speed, even if you remove the noise of creating and
destroying 100s of threads.
> Reduce number of threads created by Resolver during a startup of OSGi-based
> applications
> ----------------------------------------------------------------------------------------
>
> Key: FELIX-5247
> URL: https://issues.apache.org/jira/browse/FELIX-5247
> Project: Felix
> Issue Type: Improvement
> Components: Framework, Resolver
> Affects Versions: framework-5.4.0, resolver-1.8.0
> Reporter: Dmitry Konstantinov
> Labels: performance
> Attachments: karaf_thread_creation.png
>
>
> Thread creation is a quite expensive operation, so it make sense to reuse
> threads in ResolverImpl if they are needed to split some task and do it in
> parallel.
> For example: Apache Karaf startup with several features can install about 300
> bundles. If each one will create Runtime.getRuntime().availableProcessors()
> threads - so, during a startup about 1000 threads will be created only by
> Resolver (in case of a server machine even much more). Thread creation takes
> let's say (depends on machine, JDK, OS, etc) about 10-20 ms, so we are
> spending about 1-2 seconds of startup time only to create some threads.
> it make sense to create a thread pool once (with a configurable thread
> number) and reuse it for resolving of different bundles.
> Threads creation, stack examples:
> {noformat}
> java.lang.Thread.<init>(ThreadGroup, Runnable, String, long) Thread.java
> java.util.concurrent.Executors$DefaultThreadFactory.newThread(Runnable)
> Executors.java:613
> java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor,
> Runnable) ThreadPoolExecutor.java:612
> java.util.concurrent.ThreadPoolExecutor.addWorker(Runnable, boolean)
> ThreadPoolExecutor.java:925
> java.util.concurrent.ThreadPoolExecutor.execute(Runnable)
> ThreadPoolExecutor.java:1357
> org.apache.felix.resolver.ResolverImpl$EnhancedExecutor.execute(Runnable)
> ResolverImpl.java:2436
> org.apache.felix.resolver.ResolverImpl$1Computer.run() ResolverImpl.java:1150
> org.apache.felix.resolver.ResolverImpl$EnhancedExecutor$1.run()
> ResolverImpl.java:2442
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker)
> ThreadPoolExecutor.java:1142
> java.util.concurrent.ThreadPoolExecutor$Worker.run()
> ThreadPoolExecutor.java:617
> java.lang.Thread.run() Thread.java:745
> {noformat}
> {noformat}
> java.lang.Thread.<init>(ThreadGroup, Runnable, String, long) Thread.java
> java.util.concurrent.Executors$DefaultThreadFactory.newThread(Runnable)
> Executors.java:613
> java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor,
> Runnable) ThreadPoolExecutor.java:612
> java.util.concurrent.ThreadPoolExecutor.addWorker(Runnable, boolean)
> ThreadPoolExecutor.java:925
> java.util.concurrent.ThreadPoolExecutor.execute(Runnable)
> ThreadPoolExecutor.java:1357
> org.apache.felix.resolver.ResolverImpl$EnhancedExecutor.execute(Runnable)
> ResolverImpl.java:2436
> org.apache.felix.resolver.ResolverImpl.calculatePackageSpaces(Executor,
> ResolverImpl$ResolveSession, Candidates, Collection) ResolverImpl.java:1158
> org.apache.felix.resolver.ResolverImpl.checkConsistency(Executor,
> ResolverImpl$ResolveSession, List, List, Candidates, Map, Map, boolean)
> ResolverImpl.java:471
> org.apache.felix.resolver.ResolverImpl.resolve(ResolveContext, Executor)
> ResolverImpl.java:347
> org.apache.felix.resolver.ResolverImpl.resolve(ResolveContext)
> ResolverImpl.java:158
> org.apache.felix.framework.StatefulResolver.resolve(Set, Set)
> StatefulResolver.java:431
> org.apache.felix.framework.Felix.resolveBundleRevision(BundleRevision)
> Felix.java:4118
> org.apache.felix.framework.Felix.startBundle(BundleImpl, int) Felix.java:2124
> org.apache.felix.framework.BundleImpl.start(int) BundleImpl.java:998
> org.apache.felix.framework.BundleImpl.start() BundleImpl.java:984
> org.apache.karaf.features.internal.FeaturesServiceImpl.startBundle(InstallationState,
> Bundle) FeaturesServiceImpl.java:520
> org.apache.karaf.features.internal.FeaturesServiceImpl.installFeatures(Set,
> EnumSet) FeaturesServiceImpl.java:478
> org.apache.karaf.features.internal.FeaturesServiceImpl.installFeature(Feature,
> EnumSet) FeaturesServiceImpl.java:419
> org.apache.karaf.features.internal.FeaturesServiceImpl.installFeature(String,
> String, EnumSet) FeaturesServiceImpl.java:394
> org.apache.karaf.features.internal.FeaturesServiceImpl.installFeature(String,
> EnumSet) FeaturesServiceImpl.java:364
> {noformat}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)