Thanks for the info - that was informative!
I'm still not sold on keeping the DOM tree though. I seem to recall Adam
Heath doing a memory-use analysis a few years ago and he discovered that
even keeping a reference to a String from the DOM kept the whole tree in
memory. That is why he did all those String.intern()s in the models. I
can't be sure though, my memory is a bit foggy on that.
Adrian Crum
Sandglass Software
www.sandglass-software.com
On 1/6/2014 5:49 PM, David E. Jones wrote:
On Jan 6, 2014, at 12:58 PM, adrian.c...@sandglass-software.com wrote:
Quoting "David E. Jones" <d...@me.com>:
On Jan 6, 2014, at 12:26 PM, adrian.c...@sandglass-software.com wrote:
There are two problems with using DOM trees in OFBiz:
1. They consume a lot of memory. Keep in mind the entire XML file is kept in
memory, not just the bits you are interested in.
The parsed version is kept in memory, that is true, but for each
screen/form/etc you just keep the node object for the top-level element. Under
that element the only stuff it would keep around by default that you don't
need/want (but could be eliminated with a little code) is comment elements.
2. They are not thread-safe.
They should be used read-only, so unless someone does something funny thread
safety isn't an issue. On that note, the same is true for the shared objects in
the current OFBiz widget implementations.
And that is the problem we have now. Many contributors/committers will not understand
what should and shouldn't be done with DOM nodes, and consequently they will do things
they shouldn't. History has proven that, given the opportunity, OFBiz developers will
"do something funny" with the code.
Over the last few years, the framework code-base has been moving toward
immutable shared objects, and I think that is the safest strategy to use. We
have fixed numerous bugs going that route.
I understand your perspective and I appreciate it - make code thread-unsafe for
the sake of convenience. But that strategy exists currently in OFBiz legacy
code and it keeps hurting us.
What I find interesting about your proposal is how similar it is to what I
proposed years ago - make the widgets lightweight representations of their XML
files. The screen widget models would contain Lists of model Elements, and the
model Elements would contain Maps of Element Attributes. At the time you
rejected that idea - you said performance would suffer by making the widget
models that generic. Now you're suggesting we skip the models altogether and
just use the DOM tree. So, what has changed your opinion?
My concerns about performance were clearly overblown. After trying the direct
node tree and profiling performance I now know it doesn't result in much of a
performance difference.
In other words, the direction you proposed is a good one and would simplify
code, and letting FTL walk the node tree instead of Java code is just as fast
and that little step eliminates a bunch more framework code and at the same
time makes it far more flexible and extensible. IMO the minor impact on runtime
performance is well worth the additional flexibility. It makes the tools usable
in so many more situations where you would otherwise need to drop to plain FTL
instead of using the form widget or certain parts of the screen widget, and
addresses many of the concerns that push people to using other web UI
frameworks.
BTW, from profiling work in Moqui Framework I found it was really other stuff
that killed performance, little things you wouldn't expect sometimes like how
long it takes to call System.currentTimeMillis(). FTL and Groovy are
impressively fast for what they do and JVMs do so much better with Map and List
operations (iteration, add/put, get, etc) than they did when OFBiz was young,
especially once the JIT natively compiles that frequently used code, that the
overhead barely shows up in profiling results.
BTW2, in early profiling a few years ago with Groovy there was noticeable
overhead from on the fly object and method binding and such, but much of this
changed with Groovy 2 when they incorporated features from Groovy++ to more
quickly bind based on types declared or casted in the code, so it runs quite a
bit faster with a little more effort in declaring types (as opposed to using
Object or def all over the place). There is still somewhat of a performance
difference in doing simplified method names (like foo.bar versus foo.getBar()),
but even that doesn't show up in profilers like it used to with Groovy (so all
the effort I put into Moqui making such changes don't matter so much any more
:) ).
One thing about thread safety with this approach is that there is SO little
code, the vast bulk of it is in the FTL macros. The framework code just has to
parse the XML file, grab the desired top-level node, wrap it so FTL can use it
(in Moqui I implemented a simple wrapper for the Groovy Node object to
implement the FTL node interface), then pass it to FTL when rendering the
template. That's really it. The FTL macros will also need framework code to
call back into to do things like including forms, FTL files, other screens,
etc... but that is also pretty small/simple code.
I was hesitant about this approach at first, in spite of the great flexibility,
but in Moqui it has worked well... the code for that is about 3 years old now
with hundreds of screens running on various production instances (that I'm
aware of anyway, it's like OFBiz in that I often don't find out about projects
and even deployed instances either at all or until well after they are in
production).
-David