By changing the lifecycle of the target instance I mean that it would
be created eagerly (on source reference creation) rather than lazily
(on source reference invocation) as is done currently.  From looking
at the new code I believe this is what would happen.  (If I have
misunderstood, please correct me.)

An example of the difference is that if a conversational scoped
component A references a stateless scoped component B and invokes it
ten times through the same reference within the same conversation,
at present we would create ten copies of B, one per invocation.
With this new code, we would create one copy of B at the time that
the A instance is created.  This changes the lifecycle of B.  It is
arguably a change for the better, but it is still a change.

Now consider a stateless instance with references to other stateless
components.  For a long chain of references and services (A -> B -> C
-> D -> E -> F), all six objects would be created at the same time when
the A instance is created, rather than just creating the A instance
and a proxy for B.  Depending on the execution path through A, it's
possible that five of these six objects will never be used.  This
doesn't seem good to me.  I'm not surprised that our tests don't pick
this up, because it isn't easy to test for this kind of thing.
However, it can cause resource and performance issues in a real-world
environment because of an excessive number of object creations and
garbage collection cycles.

One way to get the best of both worlds could be to inject a proxy
initially and replace it with a direct instance pointer when the proxy
is first invoked.  This will need more code than the current proposed
approach, but I think it may be worth doing for the efficiency
benefits.  Ideally we would prototype different approaches to see
which one yields the best tradeoff in terms of overall execution
efficiency  and resource consumption.  We don't have time to do this
before the 1.0 release.

  Simon

Raymond Feng wrote:

Please keep in mind that in my proposal we optimize only if the target scope is stateless or composite. And the injection is happening for each source instance using a object factory that underneath look up the target instance from the scope container. I believe it's safe and it doesn't change the lifecycle of the target instance at all.

Here is the code I modified in "org.apache.tuscany.sca.implementation.java.invocation.JavaComponentContextProvider.java" and the build is successful.

private static class OptimizedObjectFactory<T> implements ObjectFactory<T> {
       private ScopeContainer scopeContainer;

       public OptimizedObjectFactory(ScopeContainer scopeContainer) {
           super();
           this.scopeContainer = scopeContainer;
       }

       public T getInstance() throws ObjectCreationException {
           try {
               return (T)scopeContainer.getWrapper(null).getInstance();
           } catch (TargetResolutionException e) {
               throw new ObjectCreationException(e);
           }
       }

   }

private <B> ObjectFactory<B> createObjectFactory(Class<B> interfaze, RuntimeWire wire) {
       Binding binding = wire.getSource().getBinding();
       // Check if it's wireable binding for optimization
       if (binding instanceof WireableBinding) {
           WireableBinding wireableBinding = (WireableBinding)binding;
           Component component = wireableBinding.getTargetComponent();
           if (component != null) {
Implementation implementation = component.getImplementation();
               // Check if the target component is java component
               if (implementation instanceof JavaImplementation) {
JavaImplementation javaImplementation = (JavaImplementation)implementation; if (interfaze.isAssignableFrom(javaImplementation.getJavaClass())) { ScopedRuntimeComponent scopedComponent = (ScopedRuntimeComponent)component; ScopeContainer scopeContainer = scopedComponent.getScopeContainer();
                       Scope scope = scopeContainer.getScope();
if (scope == Scope.COMPOSITE || scope == Scope.STATELESS || scope == Scope.SYSTEM) {
                           boolean optimizable = true;
for (InvocationChain chain : wire.getInvocationChains()) { if (chain.getHeadInvoker() != chain.getTailInvoker()) {
                                   optimizable = false;
                                   break;
                               }
                           }
                           if (optimizable) {
return new OptimizedObjectFactory<B>(scopeContainer);
                           }
                       }
                   }
               }
           }
       }
       return new WireObjectFactory<B>(interfaze, wire, proxyFactory);
   }

Thanks,
Raymond

----- Original Message ----- From: "Simon Nash" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Thursday, September 13, 2007 1:42 AM
Subject: Re: Optimize the reference injection for java components


If I understand this correctly, it would affect the lifecycle of
the target component instance.  So when A has a reference to B,
the creation of A currently involves creating and injecting a B proxy
but not a B instance.  With this change, I think the creation of A
would involve creating a B instance and injecting a reference to this
B instance into A.  And if B references C, this would in turn involve
creating a C instance and injecting its reference into B (and so on).

I think there could be many consequences of this change, some of which
may not be desirable.  Creation on first invocation is easy to understand
and consistent, and I'd be concerned about changing this.  A related
consideration is some of the callback cases that currently don't quite
work as I would expect, because injection can only happen when an
instance is created.  I think there may be cases where we should be
injecting/binding a callback reference when the forward call is
received and disptached to an instance that already exists, and I'm
working on a use case description for this.

I would prefer to defer this change until after 1.0 so that we can
discuss it more fully to consider all the implications, and coordinate
it with resolving the callback issues if we agree that a change is
needed there.

  Simon

Raymond Feng wrote:

Hi,

We use either JDK or CGLib proxies in reference injections for java components. It is a bit heavy and unnecessary for some cases. I now add a simple optimization to inject the implementation instance directly if the following criteria are met:

1) Both the source and target are java components
2) The binding is local SCA binding
3) The target implementation class implements/extends the source interface/class
4) The target component scope is either STATELESS or COMPOSITE
5) There is only one invoker (JavaImplementationInvoker) in each invocation chain for all the operations

What do you think?

Thanks,
Raymond





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to