> From: Leo Simons [mailto:[EMAIL PROTECTED]]
>
>
> > > 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 =)
It gets tiring. Why not just not make it possible?
> > 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.
Exactly. Which means that the CM needs a better query for the
instance of the component--which we can provide with the interface
I proposed.
> basically, you substitute exception handling for a test
> against "null". This is not an advantage.
Sure it is. The real benefit is when you have multiple
components you have to work with--and they are mutually
exclusive.
That "null" is to remove the need for the hasComponent()
method--which is obvious. We haven't reached critical
code yet, so no exception is necessary.
>
> 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
> }
Rewritten because all Requests were handled in the compose() method:
doAction() throws ActionException
{
ActionHandler handler =
(ActionHandler)m_manager.lookup(m_handlerReq);
final Object result = handler.doSomething();
m_manager.release( handler );
return result;
// no need to worry about missing components because we took
// care of that in the compose() method!
}
<snip>both misapplications</snip>
> Exceptions are _good_. try/catch is better than if/else in
> cases like this.
See the comment. You obviously didn't see my example in the
first message I posted. The Request objects are able to be
cached.
>
> > We saved three lines of code, and increased readability and
> > comprehensibility of the code at the same time!
>
> I disagree. See samples.
In the way that I wrote the method, we saved 8 lines. It is
obvious that the component is required. We don't have to verify
its existance every time we request the the component. We only
have to reuse the request object!
Are you getting where I am coming from?
> > 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.
And one for finally.
> > > 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?
Not with strings as keys!
> > > /**
> > > * 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.
Not to meantion the protection that a Request from one container
isn't guaranteed to work in another container.
>
> I think the bottleneck is usually elsewhere. I propose to
> leave the responsibility for optimisation outside of the
> ComponentManager interface.
Any time you call toString(), it is a very expensive routine.
Called several times in the critical path, and it can easily
account for 30% of your processing time.
> 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?
Of course you did. You are also missing the fact that pulling
a component from an array is quicker than pulling one from a hash.
You also are forgetting how hashes work.
Take a look at the BucketMap for clarity on the subject. To make
a long story short, a HashMap truncates the hashCode() value to
make it fit inside an internal array (I am sure there are different
uses, but bear with me). If the hash algorithm is good, it will
spread the entries fairly even within the array. However, if you
have 1000 components and 100 entries in an array, we still have
at least 10 nodes in each array entry. The hashmap has to iterate
through those nodes to find an exact match. That means calling
equals() on each key.
What is faster, comparing strings or longs?
"org.apache.avalon.excalibur.datasource.DatasourceComponent/default"
"org.apache.avalon.excalibur.datasource.DatasourceComponent/special"
56
57
Since many components have the first part the same, we don't see a
difference until we have iterated over ~59 characters!
I am suggesting moving the hashing part of component resolution
to the initialization of a component rather than the runtime.
It takes almost no time at all for a container to call:
return m_components[req.key];
String operations and converting StringBuffers to Strings (what happens
implicitly when you operate on XYZ + "foo") are expensive--esp. when
many characters are the same.
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>