Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ratz2019-03-07 09:35:39 -0500
committerAlexander Kurtakov2019-03-29 12:56:29 -0400
commitebdcf4f406e63303db84f7a2884e6e0e3f42cc21 (patch)
treec306ce6cd1c0151ee81912216eaf8861f2d3a0a2
parent0a9dd014a1e8c0d630baf25c77ca28188632b27d (diff)
downloadrt.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>
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java63
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java18
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/2018-12/content.jarbin0 -> 3357992 bytes
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
new file mode 100644
index 000000000..7f3cc65ea
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/2018-12/content.jar
Binary files differ

Back to the top