From 142dd30788dd179a4c525483cb23e7c16eed3128 Mon Sep 17 00:00:00 2001 From: Remy Masson Date: Thu, 28 Nov 2019 18:47:13 +0100 Subject: [PATCH] Optimize Dependency.getService() 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 --- .../ipojo/handlers/dependency/Dependency.java | 80 +++++-------------- .../felix/ipojo/util/DependencyModel.java | 6 +- 2 files changed, 27 insertions(+), 59 deletions(-) diff --git a/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java index db3018bf3a0..e8e8f028aa6 100644 --- a/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java +++ b/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java @@ -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 list = new ArrayList(); - 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 objs = new ArrayList(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 list = new ArrayList(); - 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((Set) obj); + } + else { + // We already have a list + return obj; + } + } + else { + return usage.getObject(); } } diff --git a/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java b/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java index 10407870ee7..a0e4cba0547 100644 --- a/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java +++ b/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java @@ -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 ? */ @@ -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.