For a while now I have been contemplating
replacing the Equinox DS implementation with the Felix SCR/DS implementation
for use in Equinox/Eclipse. There is no longer any active committers
working on the Equinox SCR/DS implementation. I work closely with
one of the lead committers of the Felix SCR/DS implementations (who happens
to work for the same company as me). For that reason I don't have
resources to spend on maintaining the Equinox SCR/DS implementation. Nobody
else has step forward to take over the implementation of Equinox DS.
For the Mars release I plan on moving
the Felix implementation for Equinox/Eclipse. So this is a last request
to the community. If you have interest, skills and time to contribute
to the Equinox DS implementation let us know, otherwise I am moving forward
with using the Felix SCR/DS implementation for Mars.
Colin Williams <colinw@xxxxxxxxxxxxxxxxxx>
mailing list <equinox-dev@xxxxxxxxxxx>
11/25/2014 06:46 PM
Equinox DS Performance Problem
This is a follow-up to my forum post , because I have
more information now and firmly believe this is a problem with Equinox,
and not my code. I have a simplified test case that duplicates the problem
, and have verified that Felix does not exhibit the same behavior.
When firing up a new instance of a Declarative Services
component, either a regular component or a newInstance of a ComponentFactory,
Equinox checks for dependency cycles ( and , for regular components
and component factory instances, respectively). Unfortunately, it does
this by walking the entire list of components and factory instances to
check for dependencies, and then walking the entire dependency graph to
check for cycles (see  and ). After checking for cycles, it then
walks the entire list again  to check for components that may need to
be disabled based on the new dependency graph.
Now, I'm not sure why the dependency cycle checking is
necessary when activating a new factory instance, since presumably it would
have been checked when the component was resolved or at least the first
time an instance of that factory was created. Even if it is necessary every
time, though, wouldn't it only be necessary to check the portion of the
dependency graph that is reachable from the new instance, rather than the
entire dependency graph of all enabled components? And then furthermore,
wouldn't it only be necessary to check the same list of potentially affected
components for ones that need to be disabled, rather than all of them?
As a result of this, Equinox exhibits O(n^2) runtime in
activating new components or creating new instances of factory components,
based on the number of components in the runtime and the complexity of
the dependency graph. In my test case , a fairly simple dependency graph
(B->C->D), which is then referenced by 3000 factory instances (A->B),
takes minutes to start because of this (see ). Adding this bundle to
a Felix container results in Felix starting the bundle and all 3000 factories
I will say that I'm not particularly familiar with the
Equinox internals, but I have added timing information into a local copy
of the DS project, and can verify that findDependencyCycles and resolveEligible
both take an excessive amount of time, proportionate to the number of total
components in the system. I'm also not very familiar with the Felix internals,
but I can't see that Felix does any dependency cycle checking when creating
a new factory instance ().
I hope this was detailed enough to explain the problem
I'm experiencing. Can anyone verify that this is an issue, or explain why
it needs to be done? Or offer workaround suggestions to allow us to still
use DS ComponentFactories with more than a few hundred services/factories?