avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leo Simons <leosim...@apache.org>
Subject RE: ContainerManager and Sub-containers
Date Wed, 05 Jun 2002 15:34:06 GMT
> > String operations can usually be cached. I know zip about 
> > cocoon, basically, but why is it not possible to have
> > 
> > static String Generator.FOO_ROLE = Generator.ROLE + "/fooo"!;
> 
> However, for most people it is just quicker to do this:
> 
> manager.lookup (Generator.ROLE + "/fooo");

make sure you tell everyone you can influence not to! We really need
that "best practices" stuff =)

> The purpose of the Generator.ROLE + "/foo" is not to arbitrarily
> select between several implementations of a Generator, but to
> further define the _ROLE_.

While not the purpose, I can see people misusing it in that way.

> > > Here is something that I have been thinking about lately.
> > > How can we have our cake and eat it too?  How can we have a fast 
> > > performing component hash without the limitations of the String.
> > 
> > 1 - don't use String (use int, long, char[])
> > 2 - cache Strings (define Strings as early as possible, 
> > minimise operations on String, cache operations on String)
> > 
> > the advantage of 1 is a cleaner (smaller) implementation. The 
> > advantage of 2 is a more intuitive API. 
> 
> And my proposal merged the two advantages!

Ehm, it merges the two solutions.

> Comparison (the component may not exist):
> 
> OLD CM
> ------
> TestComponent myComp = null;
> 
> try
> {
>     myComp = (TestComponent) manager.lookup( TestComponent.ROLE );
> 
>     myComp.doSomething();
> }
> catch (ComponentException ce)
> {
>     getLogger().error("Missing component", ce);
> }
> finally
> {
>     if (null != myComp) manager.release( myComp );
> }
> 
> 
> NEW CM
> ------
> Request req = manager.createRequest( TestComponent.ROLE );
> 
> if (null == req)
> {
>     getLogger().error("Missing component");
> }
> else
> {
>     TestComponent myComp = manager.lookup( req ); // guaranteed to be
> there
>     myComp.doSomething();
>     manager.release(myComp);
> }

basically, you substitute exception handling for a test against "null".
This is not an advantage.

good:

doAction() throws ActionException
{
	ActionHandler handler = null;
	try
	{
		final ActionHandler handler =
			(ActionHandler)m_manager.lookup(
				ActionHandler.ROLE );
		final Object result = handler.doSomething();
		m_manager.release( handler );
		return result;
	}
	catch( ComponentException ce )
	{
		getLogger.error("Missing Component", ce);
		throw new ActionException("Sorry!", ce);
	}
	// no need to release handler if a ComponetException occurs
}

as opposed to:

doAction()
{
	final ActionHandler handler = (ActionHandler)m_manager.lookup(
			ActionHandler.ROLE ); /* no reason we can't
		drop the exception in this method if we want */
	if( null == handler )
	{
		getLogger.error("Missing Component");
		return null;
		// no need to release handler if there is none
	}

	final Object result = handler.doSomething();
	m_manager.release( handler );
	return result;
}

or:

doAction()
{
	final Request request = m_manager.createRequest(
			ActionHandler.ROLE );
	if( null == request )
	{
		getLogger.error("Missing Component");
		return null;
	}
	final ActionHandler handler = (ActionHandler)m_manager.lookup(
			ActionHandler.ROLE );

	final Object result = handler.doSomething();
	m_manager.release( handler );
	return result;
}


Exceptions are _good_. try/catch is better than if/else in cases like
this.

> We saved three lines of code, and increased readability and
> comprehensibility
> of the code at the same time!

I disagree. See samples.

>  By three lines of code, I am counting
> every
> line that has text (excluding comments and blank lines).  As for
> complexity analysis you add one for every block of code (i.e. every time
> you
> have a new bracket).  We even saved here.

The exception-based method has two (one for try, one for catch), the
non-exception-based string method has one, and the request-object-based
method has one.

However, I think complexity doesn't really increase when using
exceptions.

The use of the request object does not reduce complexity, though.

> > How often do you need to server millions of requests a day 
> > where the bottleneck is not somewhere else?
> 
> 9 times out of 10, the problem is in synchronization between many
> different
> threads.  The ECM is one major source of thread contention issues.
> Fortress
> is proof that by removing as many chances for thread contention as
> possible
> dramatically increases the speed in which you can resolve requests.
> 
> Using the Request based component resolution, we gain further benefits
> by
> the ability to arange the components in any fashion we wish.  We could
> put
> them all in an array for all we care.  There won't need to be any
> synchronization unless we replace an entry.  We can further increase the
> speed of the whole system.

Is this not possible in a way completely internal to the CM?

> >     /**
> >      * Keep current method, basically making the call to
> >      * createRequest internal. Also means these changes can probably
> >      * be done somewhere in a future avalon 4 release as no existing
> >      * functionality is removed or changed.
> >      * Note that the CM could still do some smart caching of the
> >      * generated Request objects internally.
> >      */
> >     Object lookup( String role ) throws RuntimeException;
> 
> To maintain compatibility it would be ComponentException--not
> RuntimeException.

gotcha. What I ment.

What I see:

You think there are many cases where string creation or string hashing
are the bottleneck for a system that needs performance. You propose to
use a request object for the CM, basically a container for a long, to
solve this.
The request object is then retrieved, using string creation and string
hashing, from the CM.

I think the bottleneck is usually elsewhere. I propose to leave the
responsibility for optimisation outside of the ComponentManager
interface.

If the request object is not cached by the user, there is little
performance gain. If the user is smart enough to cache the request
object, he is probably also smart enough to cache the lookup string and
the requested component, meaning there is no bottleneck.

did I miss something?

- Leo



--
To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>


Mime
View raw message