[ 
https://issues.apache.org/jira/browse/FELIX-3624?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13431755#comment-13431755
 ] 

Marcel Offermans commented on FELIX-3624:
-----------------------------------------

Also, it would be nice to include some kind of test that performs the 
measurements that you have been using to write this solution. That way we can 
easily evaluate what the original problem was and how much better it has become.
                
> Performance tuning solution for BundleRepository/ResolverImpl
> -------------------------------------------------------------
>
>                 Key: FELIX-3624
>                 URL: https://issues.apache.org/jira/browse/FELIX-3624
>             Project: Felix
>          Issue Type: Improvement
>          Components: Bundle Repository (OBR)
>         Environment: Geronimo3 + BundleRepository 1.6.6
>            Reporter: SheldonShao
>            Priority: Critical
>         Attachments: Felix_ResolverImpl.png, 
> Felix_ResolverImpl_AfterTuning.png, ResolverImpl.java
>
>
> There are too many numebers of method calling about checking whether 
> capabities are matched with requiment in ResolverImpl.searchResources.
> This is a performance issue of ResolverImpl.resolve.
> If it creates a capabity to resource+capabity mapping first. Then leverage 
> this cache to do requirment matching.  It will get better performance.
> Here is part of code.  More details please check attachments.
>       private final Map m_capabilitiesCache = new HashMap(8192);
>       private String getKey(String filter, String prefix) {
>               if (filter != null) {
>                       int index = filter.indexOf(prefix);
>                       if (index > 0) {
>                               int end = filter.indexOf(SUFFIX, index + 
> prefix.length());
>                               if (end > index) {
>                                       return filter.substring(index, end);
>                               }
>                       }
>               }
>               return null;
>       }
>       private String getKey(Requirement requirement) {
>               String key = null;
>               String name = requirement.getName();
>               String filter = requirement.getFilter();
>               if (Capability.BUNDLE.equals(name)) {
>                       key = getKey(filter, PREFIX_SYMBOLICNAME);
>               } else if (Capability.PACKAGE.equals(name)) {
>                       key = getKey(filter, PREFIX_PACKAGE);
>               } else if (Capability.SERVICE.equals(name)) {
>                       key = getKey(filter, PREFIX_SERVICE);
>               } else if (Capability.FRAGMENT.equals(name)) {
>                       key = getKey(filter, PREFIX_HOST);
>               } else {
>                       key = PREFIX_CAPABILITY + name;
>               }
>               return key;
>       }
>       private static final String PREFIX_SYMBOLICNAME = "symbolicname=";
>       private static final String PREFIX_PACKAGE = "package=";
>       private static final String PREFIX_SERVICE = "service=";
>       private static final String PREFIX_HOST = "host=";
>       private static final String PREFIX_CAPABILITY = "capability=";
>       private static final char SUFFIX = ')';
>       private void initCache(Capability[] capabilities, Resource resource) {
>               Capability cap;
>               Map properties;
>               String name;
>               for (int j = 0; j < capabilities.length; j++) {
>                       cap = capabilities[j];
>                       String key = null;
>                       properties = cap.getPropertiesAsMap();
>                       name = cap.getName();
>                       if (Capability.BUNDLE.equals(name)) {
>                               key = PREFIX_SYMBOLICNAME + 
> properties.get("symbolicname");
>                       } else if (Capability.PACKAGE.equals(name)) {
>                               key = PREFIX_PACKAGE + 
> properties.get("package");
>                       } else if (Capability.SERVICE.equals(name)) {
>                               key = PREFIX_SERVICE + 
> properties.get("service");
>                       } else if (Capability.FRAGMENT.equals(name)) {
>                               key = PREFIX_HOST + properties.get("host");
>                       } else {
>                               key = PREFIX_CAPABILITY + name;
>                       }
>                       List caps = (List) m_capabilitiesCache.get(key);
>                       if (caps == null) {
>                               caps = new ArrayList(2);
>                               m_capabilitiesCache.put(key, caps);
>                       }
>                       caps.add(new ResourceCapabilityImpl(resource, cap));
>               }
>       }
>       private void initCache(Resource[] locals) {
>               Resource resource;
>               for (int i = 0; i < locals.length; i++) {
>                       resource = locals[i];
>                       Capability[] capabilities = resource.getCapabilities();
>                       if (capabilities != null && capabilities.length > 0) {
>                               initCache(capabilities, resource);
>                       }
>               }
>       }
> /**
>        * Searches for resources that do meet the given requirement
>        * 
>        * @param req
>        *            the the requirement that must be satisfied by resources
>        * @param resources
>        *            list of resources to look at
>        * @return all resources meeting the given requirement
>        */
>       private List searchAllResources(Requirement req, Resource[] locals, 
> Resource[] remotes) {
>               String key = getKey(req);
>               if (key != null) {
>                       List matchingCapabilities = new ArrayList();
>                       List capabilities = (List) m_capabilitiesCache.get(key);
>                       if (capabilities != null) {
>                               for (int capIdx = 0, size = 
> capabilities.size(); capIdx < size; capIdx++) {
>                                       checkInterrupt();
>                                       ResourceCapabilityImpl capImpl = 
> (ResourceCapabilityImpl) capabilities
>                                                       .get(capIdx);
>                                       if 
> (req.isSatisfied(capImpl.getCapability())) {
>                                               
> matchingCapabilities.add(capImpl);
>                                       }
>                               }
>                       }
>                       return matchingCapabilities;
>               } else {
>                       List matchingCapabilities = searchResources(req, 
> locals);
>                       matchingCapabilities.addAll(searchResources(req, 
> remotes));
>                       return matchingCapabilities;
>               }
>       }
>       public synchronized boolean resolve(int flags) {
>               m_capabilitiesCache.clear();
>               
>               // Find resources
>               Resource[] locals = getResources(true);
>                                     //Create cache here
>               initCache(locals);
>               Resource[] remotes = getResources(false);
>               initCache(remotes);
>                                    .....
>                 }
>                
>       private Resource searchResources(Requirement req, Set resourceSet)
>                       private List searchResources(Requirement req, 
> Resource[] resources) 
>                
>                   were also changed for leveraging this cache.
>               

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to