You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2017/08/21 08:58:59 UTC

[3/9] karaf git commit: KARAF-5314 Added a features cache that increases the performance of the filtering of the required features from the available features.

KARAF-5314 Added a features cache that increases the performance of the filtering of the required features from the available features.

The performance of the filtering logic decresed when the java streams API was used in 4.1 compared to for loops in 4.0. I reverted the filtering logic to use for loops and also introduced a features cache. This increased the performance by a huge margin, almost 20X faster when there are ~900 available features and ~300 required features from a highly complex and huge feature dependency tree.


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/3cbd810e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/3cbd810e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/3cbd810e

Branch: refs/heads/model_features
Commit: 3cbd810ea37e837950f1f8427f793c878423ba7a
Parents: 658ee48
Author: Vinay Shankar (e24113) <Vi...@cmegroup.com>
Authored: Fri Aug 18 13:55:58 2017 -0500
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Fri Aug 18 23:22:25 2017 +0200

----------------------------------------------------------------------
 .../apache/karaf/profile/assembly/Builder.java  | 38 +++++++++++++++-----
 1 file changed, 30 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/3cbd810e/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 27b83a6..e9cc67e 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -39,6 +39,7 @@ import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
@@ -49,7 +50,6 @@ import java.util.function.Function;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
@@ -805,10 +805,11 @@ public class Builder {
             allInstalledFeatures.addAll(repo.getFeature());
         }
         Set<Feature> installedFeatures = new LinkedHashSet<>();
+        Map<String, Map<Version, Feature>> featuresCache = new HashMap<>();
         // Add boot features for search
         allInstalledFeatures.addAll(allBootFeatures);
         for (String feature : installedEffective.getFeatures()) {
-            addFeatures(allInstalledFeatures, feature, installedFeatures, true);
+            addFeatures(allInstalledFeatures, feature, installedFeatures, true, featuresCache);
         }
         ArtifactInstaller installer = new ArtifactInstaller(systemDirectory, downloader, blacklistedBundles);
         for (Feature feature : installedFeatures) {
@@ -882,7 +883,8 @@ public class Builder {
 
         // Compute startup feature dependencies
         Set<Feature> bootFeatures = new HashSet<>();
-        addFeatures(allBootFeatures, generated.getName(), bootFeatures, true);
+        Map<String, Map<Version, Feature>> featuresCache = new HashMap<>();
+        addFeatures(allBootFeatures, generated.getName(), bootFeatures, true, featuresCache);
         for (Feature feature : bootFeatures) {
             // the feature is a startup feature, updating startup.properties file
             LOGGER.info("   Feature " + feature.getId() + " is defined as a boot feature");
@@ -1239,14 +1241,16 @@ public class Builder {
         return startupEffective;
     }
 
-    private void addFeatures(Set<Feature> allFeatures, String feature, Set<Feature> features, boolean mandatory) {
+    private void addFeatures(Set<Feature> allFeatures, String feature, Set<Feature> features, boolean mandatory, Map<String, Map<Version, Feature>> featuresCache) {
         String name;
+        Version osgiVersion;
         VersionRange range;
         int idx = feature.indexOf('/');
         if (idx > 0) {
             name = feature.substring(0, idx);
             String version = feature.substring(idx + 1);
             version = version.trim();
+            osgiVersion = VersionTable.getVersion(version);
             if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
                 range = new VersionRange(Version.emptyVersion);
             } else {
@@ -1254,18 +1258,36 @@ public class Builder {
             }
         } else {
             name = feature;
+            osgiVersion = Version.emptyVersion;
             range = new VersionRange(Version.emptyVersion);
         }
-        Set<Feature> set = allFeatures.stream()
-                .filter(f -> f.getName().equals(name) && range.contains(VersionTable.getVersion(f.getVersion())))
-                .collect(Collectors.toSet());
+        Set<Feature> set = new HashSet<>();
+        boolean featurePresentInCache = false;
+        Optional<Map<Version, Feature>> optionalVersionFeatureMap = Optional.ofNullable(featuresCache.get(name));
+        if(optionalVersionFeatureMap.isPresent()) {
+            Optional<Feature> cachedFeature = Optional.ofNullable(optionalVersionFeatureMap.get().get(osgiVersion));
+            if(cachedFeature.isPresent()){
+                set.add(cachedFeature.get());
+                featurePresentInCache = true;
+            }
+        }
+        if(!featurePresentInCache) {
+            for (Feature f : allFeatures) {
+                if (f.getName().equals(name) && range.contains(VersionTable.getVersion(f.getVersion()))) {
+                    set.add(f);
+                    Map<Version, Feature> versionFeatureMap = Optional.ofNullable(featuresCache.get(name)).orElse(new HashMap<>());
+                    versionFeatureMap.put(osgiVersion, f);
+                    featuresCache.put(name, versionFeatureMap);
+                }
+            }
+        }
         if (mandatory && set.isEmpty()) {
             throw new IllegalStateException("Could not find matching feature for " + feature);
         }
         for (Feature f : set) {
             features.add(f);
             for (Dependency dep : f.getFeature()) {
-                addFeatures(allFeatures, dep.toString(), features, !dep.isDependency() && !dep.isPrerequisite());
+                addFeatures(allFeatures, dep.toString(), features, !dep.isDependency() && !dep.isPrerequisite(), featuresCache);
             }
         }
     }