diff options
author | Sebastian Ratz | 2019-03-07 14:35:39 +0000 |
---|---|---|
committer | Alexander Kurtakov | 2019-03-29 16:56:29 +0000 |
commit | ebdcf4f406e63303db84f7a2884e6e0e3f42cc21 (patch) | |
tree | c306ce6cd1c0151ee81912216eaf8861f2d3a0a2 /bundles | |
parent | 0a9dd014a1e8c0d630baf25c77ca28188632b27d (diff) | |
download | rt.equinox.p2-ebdcf4f406e63303db84f7a2884e6e0e3f42cc21.tar.gz rt.equinox.p2-ebdcf4f406e63303db84f7a2884e6e0e3f42cc21.tar.xz rt.equinox.p2-ebdcf4f406e63303db84f7a2884e6e0e3f42cc21.zip |
Bug 545179 - Improve CapabilityIndex performance for arbitrary
namespaces
Follow-up on I957d401c3f043daf40db13397829993fe3fc5dc2 which improves
performance for queries with arbitrary namespaces and without a "name"
property.
Change-Id: I44ebbb140242d71cba855fd1d5f6fe30e62f4aad
Signed-off-by: Sebastian Ratz <sebastian.ratz@sap.com>
Diffstat (limited to 'bundles')
3 files changed, 50 insertions, 31 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java index e742b63cd..ffdac0a33 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java @@ -47,37 +47,32 @@ import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; @SuppressWarnings("unchecked") public class CapabilityIndex extends Index<IInstallableUnit> { - private static final String NAMESPACE_EXECUTION_ENVIRONMENT = "osgi.ee"; - private final Map<String, Object> capabilityMap; - private final Set<IInstallableUnit> eeProvidersSet; + private final Map<String, Set<IInstallableUnit>> namespaceMap; + private final Map<String, Object> nameMap; public CapabilityIndex(Iterator<IInstallableUnit> itor) { - HashMap<String, Object> index = new HashMap<>(300); - Set<IInstallableUnit> eeProviders = new HashSet<>(10); + nameMap = new HashMap<>(300); + namespaceMap = new HashMap<>(10); while (itor.hasNext()) { IInstallableUnit iu = itor.next(); Collection<IProvidedCapability> pcs = iu.getProvidedCapabilities(); for (IProvidedCapability pc : pcs) { - if (NAMESPACE_EXECUTION_ENVIRONMENT.equals(pc.getNamespace())) { - eeProviders.add(iu); - } - String name = pc.getName(); - Object prev = index.put(name, iu); - if (prev == null || prev == iu) - continue; - - ArrayList<IInstallableUnit> list; - if (prev instanceof IInstallableUnit) { - list = new ArrayList<>(); - list.add((IInstallableUnit) prev); - } else - list = (ArrayList<IInstallableUnit>) prev; - list.add(iu); - index.put(name, list); + namespaceMap.computeIfAbsent(pc.getNamespace(), namespace -> new HashSet<>()).add(iu); + nameMap.compute(pc.getName(), (name, prev) -> { + if (prev == null || prev == iu) { + return iu; + } else if (prev instanceof IInstallableUnit) { + Collection<IInstallableUnit> ius = new HashSet<>(); + ius.add((IInstallableUnit) prev); + ius.add(iu); + return ius; + } else { + ((Collection<IInstallableUnit>) prev).add(iu); + return prev; + } + }); } } - this.capabilityMap = index; - this.eeProvidersSet = Collections.unmodifiableSet(eeProviders); } private Object getRequirementIDs(IEvaluationContext ctx, IExpression requirement, Object queriedKeys) { @@ -148,6 +143,7 @@ public class CapabilityIndex extends Index<IInstallableUnit> { @Override public Iterator<IInstallableUnit> getCandidates(IEvaluationContext ctx, IExpression variable, IExpression booleanExpr) { Object queriedKeys = null; + Map<String, ?> indexMapToUse = nameMap; // booleanExpression must be a collection filter on providedCapabilities // or an IInstallableUnit used in a match expression. @@ -171,12 +167,17 @@ public class CapabilityIndex extends Index<IInstallableUnit> { LambdaExpression lambda = cf.lambda; queriedKeys = getQueriedIDs(ctx, lambda.getItemVariable(), ProvidedCapability.MEMBER_NAME, lambda.getOperand(), queriedKeys); if (queriedKeys == null) { - // Special handling to support + // Special handling to support expressions for arbitrary namespaces without "name" property such as // osgi.ee; (&(osgi.ee=JavaSE)(version=1.8)) // providedCapabilities.exists(cap | cap.namespace == $0 && cap.properties ~= $1) - // in a performant way - if (NAMESPACE_EXECUTION_ENVIRONMENT.equals(getQueriedIDs(ctx, lambda.getItemVariable(), ProvidedCapability.MEMBER_NAMESPACE, lambda.getOperand(), queriedKeys))) { - return this.eeProvidersSet.iterator(); + // or + // osgi.service; (objectClass=org.osgi.service.event.EventAdmin) + // providedCapabilities.exists(cap | cap.namespace == $0 && cap.properties ~= $1) + // in a performant way as this reduces the result set significantly + queriedKeys = getQueriedIDs(ctx, lambda.getItemVariable(), ProvidedCapability.MEMBER_NAMESPACE, lambda.getOperand(), queriedKeys); + if (queriedKeys != null) { + indexMapToUse = namespaceMap; + break; } } } else { @@ -245,9 +246,9 @@ public class CapabilityIndex extends Index<IInstallableUnit> { } else if (queriedKeys instanceof Collection<?>) { matchingIUs = new HashSet<>(); for (Object key : (Collection<Object>) queriedKeys) - collectMatchingIUs((String) key, matchingIUs); + collectMatchingIUs(indexMapToUse, (String) key, matchingIUs); } else { - Object v = capabilityMap.get(queriedKeys); + Object v = indexMapToUse.get(queriedKeys); if (v == null) matchingIUs = Collections.emptySet(); else if (v instanceof IInstallableUnit) @@ -258,8 +259,8 @@ public class CapabilityIndex extends Index<IInstallableUnit> { return matchingIUs.iterator(); } - private void collectMatchingIUs(String name, Collection<IInstallableUnit> collector) { - Object v = capabilityMap.get(name); + private static void collectMatchingIUs(Map<String, ?> indexToUse, String name, Collection<IInstallableUnit> collector) { + Object v = indexToUse.get(name); if (v == null) return; if (v instanceof IInstallableUnit) diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java index 473d5f422..c98cdff73 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java @@ -293,6 +293,24 @@ public class PerformanceTest extends AbstractProvisioningTest { System.out.println(); } + public void testCapabilityQueryPerformanceOsgiService() throws Exception { + + IMetadataRepository repo = getMDR("/testData/2018-12"); + + IRequirement capability = MetadataFactory.createRequirement("osgi.service", "(objectClass=org.osgi.service.event.EventAdmin)", null, 0, 0, false); + IQuery<IInstallableUnit> capabilityQuery = QueryUtil.createMatchQuery(capability.getMatches()); + IQueryResult<IInstallableUnit> result; + + long start = System.currentTimeMillis(); + for (int i = 0; i < 1000; ++i) { + result = repo.query(capabilityQuery, new NullProgressMonitor()); + assertEquals(1, queryResultSize(result)); + assertEquals("org.eclipse.equinox.event", result.iterator().next().getId()); + } + System.out.println("1000 * CapabilityQuery for osgi.service took: " + (System.currentTimeMillis() - start) + " milliseconds"); + System.out.println(); + } + public void testIUPropertyQueryPerformance() throws Exception { IMetadataRepository repo = getMDR("/testData/galileoM7"); diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/2018-12/content.jar b/bundles/org.eclipse.equinox.p2.tests/testData/2018-12/content.jar Binary files differnew file mode 100644 index 000000000..7f3cc65ea --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/2018-12/content.jar |