[ https://issues.apache.org/jira/browse/FELIX-3624?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
SheldonShao updated FELIX-3624: ------------------------------- Attachment: (was: ResolverImpl.java) > 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_AfterTuning.png, > Felix_ResolverImpl.png, repo_for_resolver_perf.xml, ResolverImpl.diff, > ResolverImplTest.diff > > > 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