Skip to content

Commit

Permalink
Optimize Dependency.getService()
Browse files Browse the repository at this point in the history
Another kinda hardcore optimization
We're now also caching this call in the ServiceUsage
threadlocal, even if called outside of a component - as this
is the case where we actually needed the optimization
Note that the counters (inc()/dev()) done on the Usages
could be removed since we're basically not using them any longer
and using a WeakHashMap instead, hoping the GC will help us
clean out the cached services
  • Loading branch information
muryoh committed Nov 28, 2019
1 parent 6620b58 commit 142dd30
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -670,70 +670,34 @@ public Object getService() {
throw new IllegalStateException("The dependency has not enabled the `proxy` mode.");
}

Usage usage = (Usage) m_usage.get();
Usage usage = m_usage.get();
if (!usage.isUpToDate()) {
// We comes from the component who didn't touch the service.
// So we initialize the usage.
createServiceObject(usage);
}
if (usage.m_stack == 0) { // uninitialized usage.
if (usage.m_componentStack > 0) {
if (!usage.isUpToDate()) {
// We comes from the component who didn't touch the service.
// So we initialize the usage.
createServiceObject(usage);
}
usage.inc(); // Start the caching, so set the stack level to 1
m_usage.set(usage); // Required by Dalvik.
if (isAggregate()) {
Object obj = usage.getObject();
if (obj instanceof Set) {
List<Object> list = new ArrayList<Object>();
list.addAll((Set) obj);
return list;
} else {
// We already have a list
return obj;
}
} else {
return usage.getObject();
}
} else {
// External access => Immediate get.
if (isAggregate()) {
ServiceReference[] refs = getServiceReferences();
if (refs == null) {
return new ArrayList(0); // Create an empty list.
} else {
List<Object> objs = new ArrayList<Object>(refs.length);
for (ServiceReference ref : refs) {
objs.add(getService(ref));
}
return objs;
}
} else { // Scalar dependency.
ServiceReference ref = getServiceReference();
if (ref != null) {
return getService(ref);
} else {
// No service available.
// TODO Decide what we have to do.
throw new RuntimeException("Service " + getSpecification() + " unavailable");
}
}
}
} else {
// Use the copy.
// if the copy is a set, transform to a list
if (isAggregate()) {
Object obj = usage.getObject();
if (obj instanceof Set) {
List<Object> list = new ArrayList<Object>();
list.addAll((Set) obj);
return list;
} else {
// We already have a list
return obj;
}
} else {
return usage.getObject();
}
}
return getObjectFromUsage(usage);
}

private Object getObjectFromUsage(Usage usage) {
if (isAggregateUnsafe()) {
Object obj = usage.getObject();
if (obj instanceof Set) {
return new ArrayList<Object>((Set) obj);
}
else {
// We already have a list
return obj;
}
}
else {
return usage.getObject();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public abstract class DependencyModel {
/**
* Does the dependency bind several providers ?
*/
private boolean m_aggregate;
private volatile boolean m_aggregate;
/**
* Is the dependency optional ?
*/
Expand Down Expand Up @@ -737,6 +737,10 @@ public boolean isAggregate() {
}
}

protected boolean isAggregateUnsafe() {
return m_aggregate;
}

/**
* Sets the aggregate attribute of the current dependency.
* If the tracking is opened, it will call arrival and departure callbacks.
Expand Down

0 comments on commit 142dd30

Please sign in to comment.