On Jul 18, 2007, at 23:18, Jeremias Maerki wrote:
Some additional thoughts before going to bed:
- I think the static synchronized WeakHashMap should be avoided.
There's
a lot of synchronization that is performed. I suspect this will have a
bad effect on performance.
I have always assumed it would have some effect that could be
interpreted as bad.
Richard's initial version of the PropertyCache synchronized the fetch
() method, and if I remember and interpret correctly, this caused a
noticeable slowdown in performing the jUnit tests. Once I decided to
use Collections.synchronizedMap(), the speed went back to normal.
It may make more sense to have a
FlyWeightFactory (per object) per rendering run. Somebody (don't
remember who, sorry) wrote that FOP cannot bring the CPU to 100%,
probably due to synchronization issues. Could be worth investigating
since this would mean we give away CPU cicles here.
Could indeed be interesting to know if it's really the
synchronization or other aspects of FOP's architecture that would be
the cause of that. Using statics and the above utility method of
course makes performance greatly dependent on the cleverness of the
JVM implementation.
Other than that, /if/ any synchronization should be performed, then
it would seem better to do so on the lower level: with the original
patch, multiple calls to the fetch() method would be prevented from
being executed concurrently, even if none of them altered the
underlying Map.
- It's probably not the most effective way to use the Property
itself as
the key into the Map, i.e. creating throw-away instances excessively.
Working with specialized FlyWeightFactories could be more
efficient. See
http://en.wikipedia.org/wiki/Flyweight_pattern
Also my initial thought: if the Property is simply a wrapper around
an int or a String, then I'd assume that it would be better to check
for an existing instance corresponding to that base value.
Then again, I do seem to remember Richard pointing out that creating
a lot of temporary instances is quasi irrelevant in a language like
Java, especially the later JVM versions. IIRC, it has to do with the
fact that the throw-away instances never have to leave the stack --
which by itself already saves the time it takes to reserve addresses
in the heap and transfer the instances to them.
This factor does become important once you have a situation where a
pass through the constructor triggers a method call for each of a
handful of members, like in the case of the Common-bundles.
In case of the immediate Property subclasses, however, the
constructors themselves are actually very light, so it should not be
much of a problem. The bulk of the 'construction' work is carried by
the Makers and the PropertyParser.
- One of the easiest candidates for another flyweight is probably
CommonHyphenation (56K instances, 2.3MB in my example). The few member
variables could probably just be concatenated to a String (to be
used as
the key).
Interesting idea, will look into that asap.
- It could be worth looking into the difference between HashMap and
TreeMap. Maybe one is more suitable than the other. I haven't
looked at
the difference, yet.
No idea here either. Come to think of it, I've never really looked at
TreeMap before at all. I'd have to check for specific use-cases first
to see what the specific use could be here. There's no WeakTreeMap
yet, though... 8-)
Cheers
Andreas