Re: Optimising Variable to reduce instantiation overhead

Alex Twisleton-Wykeham-Fiennes <[email protected]> Thu, 23 Mar 2006 14:10:06 +0000
Newsgroups gmane.comp.java.webmacro.user
Message-ID <[email protected]>
On Thu 23 March 2006 09:32, Endre St=F8lsvik wrote:
> Hi again!
>
> | ps: Endre:  I would be *very* happy to evaluate any actual concrete code
> | that you put forward to the list towards performance increases in
> | webmacro.
>
> I must admit that I might have gotten stuck in a wrong argument-line. It
> is probably rather the full architecture that I'm annoyed with, where the
> synchronization-issues I'm raising is rather a symptom of an underlying
> problem (as I percieve it), rather than the problem in itself.

well, in which case I rephrase my statement to say that I'd be very happy t=
o=20
evaluate your proposed architectural changes to the webmacro tree against t=
he=20
current tree with respect to backwards compatability and performance.

> A question one could raise in this line of argument is rather _why_ is
> there so much hitting at the concurrentmap? Not necessarily _how to
> improve the speed_, is my point, although this is obviously also a good
> thing to evaluate.

I've been looking into this as well, and at present I don't see any trivial=
=20
ways of reducing the number of hits on the caches.  However, I'm still=20
getting up to speed on the finer points of the (very elegant) architecture=
=20
and wouldn't like to suggest any changes without validating that they don't=
=20
have some unforseen side effects.

> I will try to do some code at some point. But if there isn't a drive in
> the community to do this "disentagle" of concerns in WebMacro, we aren't
> really aligned.

I'm not personally opposed to architectural tweaks, I just find it very=20
difficult to get excited about statements that say "this is bad and should =
be=20
changed" rather than "I think that XYZ would be a better way of doing ABC a=
nd=20
here are my reasons for suggesting it".

> PS: I value the stuff you're doing. It is obviously a good effort,
> cleaning up some heavy mess that's left behind after last refactor.

I wouldn't say that it is really a heavy mess.  Each version of webmacro ha=
s=20
been faster and more flexible than the one before, I'm just adding a few mo=
re=20
tweaks to the architecture.

> PPS: re equals'n'hashCode: how does things end up in the map(s)?=20

There are two models:  either invoking CacheManager.get(Object key) and=20
manually adding it if the return is null, or invoking CacheManager.get(Obje=
ct=20
key, ResourceLoader helper) which calls back to the helper in the case of t=
he=20
the key not being found in the cache.

The majority of the time in the profiling, the items are actually in the ca=
che=20
already, but they are just being resolved.

> Are they=20
> hitting "linear storage" where one in effect ends up with a linked list,
> rather than a hashmap? This has been the issue in some of my code, where
> hashCode had a very bad distribution, and that _really_ made for slow
> accesses. Using JProfiler (my tool of choice at the moment), this was
> rather easy to find, as one may "graph-walk" the heap, and this showed
> that some elements had a _really_ long way to their GC-roots, running
> through a huge line of HashMap.Entry elements' "next" pointers.

This is generally caused by having a clumping hashcode() function on your k=
ey. =20
The number of buckets in the HashMap should automatically expand once the=20
number of items in the map exceeds the loadFactor x bucketCount on the=20
HashMap.  However, if your hashcode function returns either the same value=
=20
for multiple keys or the same (value % bucketcount) for multiple keys then=
=20
they will tend to bunch together under a single bucket before triggering th=
e=20
rebuild.  A "good" hashcode implementation will ensure a wide distribution =
of=20
keys across the initial buckets and therefore will reduce your chains.

However, every single get() call to a Map (for both HashMap, and=20
ConcurrentHashMap) will involve an invocation of hashcode() on the key to=20
find out the bucket to place the key into, followed by a call to equals() o=
n=20
all of the items within the bucket chain until it is matched.  Therefore an=
=20
innefficient algorithm for hashcode and equals can cripple the performance =
of=20
the HashMap at multiple levels.

Alex



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642