[
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