Dear Wiki user, You have subscribed to a wiki page or wiki category on "Xmlgraphics-fop Wiki" for change notification.
The following page has been changed by AndreasDelmelle: http://wiki.apache.org/xmlgraphics-fop/PropertyHandling/PropertyCache ------------------------------------------------------------------------------ Still, this type of streamlining of the stylesheet is not always possible. In contexts where the stylesheet is generated by a third-party tool, there are likely to be many XML attribute specifications that, from the point of view of the formatter would be redundant. On another note, there are also many {{{<enum>}}} properties that share the same possible values, but are not inherited. - The initial idea for further optimization in that area was given to FOP by Richard Wheeldon in a Bugzilla patch (see: https://issues.apache.org/bugzilla/show_bug.cgi?id=41044). + The initial idea for further optimization in that area was given to FOP by Richard Wheeldon in a Bugzilla patch (see: https://issues.apache.org/bugzilla/show_bug.cgi?id=41044). + In its most basic form, some {{{Property}}} subclasses that did not require a layout context for resolution were equipped with a private static {{{WeakHashMap}}} that retained all created instances to which other objects held hard references, and accompanying implementations for {{{equals()}}} and {{{hashCode()}}}. Their constructors were made inaccessible from outside the package, and instead new instances were created via a public static {{{getInstance()}}} method. That method creates a new instance, performs a {{{get()}}} on the {{{HashMap}}}, adds it if it does not exist yet, and returns either the result of the {{{get()}}} or the newly created instance. + + Since all the related constructors are simple parameter assignment constructors, like: + + {{{ + public MyProperty(int someInt, Object someObj) { + this.primitiveValue = someInt; + this.referenceValue = someObj; + } + }}} + + and the generated instances only have to be moved from the stack to the heap if they are really ''new'' instances to be added to the map, the involved overhead should be minimal in a language like Java, especially with modern VMs. The well-known warning about instantiation rates in the early days now more apply to circumstances where one would trigger a chain of constructors with every instantion (e.g. if the second assignment would be {{{this.referenceValue = new OtherClass();}}}). + + + == Structure == + + As the number of properties to which this approach was applied, began to grow, the decision was made to implement a dedicated class that could be used by any of the {{{Property}}} classes. The concern for multi-session environments was first taken into account by wrapping the {{{WeakHashMap}}} in a standard synchronized map. The {{{PropertyCache}}} itself would only have one or more {{{fetch(Object obj)}}} methods as public access points, that took care of the operations that were initially performed within the {{{Property}}} subclasses (see above), so the idiom had become simply: + + {{{ + public static Property getInstance(int someInt, Object someObj) { + return myPropertyCache.fetch(new MyProperty(someInt, someObj)); + } + }}} + + The newly created instance would either be returned from this method, or disappear into oblivion and be replaced by the corresponding entry in the map. + + After fixing some errors in the added {{{hashCode()}}} and {{{equals()}}} implementations, the first version of the {{{PropertyCache}}} was silently released to the public with FOP 0.94. No big commotion was made back then. As this was still restricted to only a handful of properties, the assumed effect would be only minimal. + + In the meantime development went further on the trunk. After reading some more documentation on multi-threading in Java and studying the concepts of concurrency and contention, it became obvious that there was a possible performance bottleneck involved in using {{{Collections.synchronizedMap();}}}. Java 1.5 has its own {{{java.util.concurrent}}} package, but FOP still targets 1.4 environments, so those could not be used. Even then, the {{{util.concurrent}}} package only offers a {{{ConcurrentHashMap}}}, no variant using {{{WeakReference}}}s, which would be needed to implement a cache that is shared by many threads. Besides that, a {{{Map}}} always contains ''mappings''. That is: every entry has a key ''and'' a value. But FOP needed only a weakly referenced key... + + The following article at IBM gave a starting point for building our very own cache: + http://www.ibm.com/developerworks/java/library/j-jtp08223/index.html + --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
