[ 
https://issues.apache.org/jira/browse/FELIX-3624?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

SheldonShao updated FELIX-3624:
-------------------------------

    Description: 
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.


              

  was:
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.

    
> 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
>         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