|
From: Drew D. <dr...@og...> - 2005-01-29 20:59:43
|
Colin Sampaleanu wrote:
> This code looks pretty interesting. I agree about it probably making
> sense to include in Spring. Drew, do you have any feel for
> performance, i.e. how big an impact there would be to using a lot of
> these expressions in a config file?
I wouldn't expect the effect to be very noticeable at all. I haven't
done any performance comparisons with bare spring contexts and
OGNL-decorated ones so all I have is my own experience with my
Hibernate/Spring/Tapestry webapps. I currently am using this on 3
different projects and have developed on these for months before popping
this configurer in, so I have a good idea of the "real world" startup
time of my contexts.
My opinion is that the OGNL parsing/evaluation is "dust on the scale"
when compared with the startup time for Spring's parsing and
(especially) Hibernate initialization. OGNL uses reflection heavily (as
does Spring), but the fact is that most of the time (probably all of the
time) you read the contexts once at startup, so any compilation step at
this point would slow down the process (the incarnation of OGNL that I'm
working on has back-ends for Janino and one for Javassist code
generation for faster expression evaluation).
Since I wrote this I went a bit off the deep end using OGNL expressions
in my contexts; I've since settled down a bit and backed off of using
them so much. The reason is that I was doing some things with OGNL that
should be done with Spring just because OGNL provides a slightly more
convenient syntax for some things (collections, mostly). I didn't do it
for performance reasons (I had a context with about 30 objects that were
configured using at least one OGNL-replaced expression each and it had
no noticeable performance impact).
The OGNL performance suite should give you an idea of the general speed
for some common operations:
performance:
[java] Constant: 100 + 20 * 5
[java] java: 3720098 iterations in 1000 ms
[java] compiled: 912719 iterations in 1000 ms (4.1 times slower
than java)
[java] interpreted: 869808 iterations in 1000 ms (4.3 times slower
than java)
[java] Single Property: bean2
[java] java: 3772105 iterations in 1000 ms
[java] compiled: 362914 iterations in 1000 ms (10.4 times slower
than java)
[java] interpreted: 167400 iterations in 1000 ms (22.5 times slower
than java)
[java] Property Navigation: bean2.bean3.value
[java] java: 3601668 iterations in 1000 ms
[java] compiled: 102586 iterations in 1000 ms (35.1 times slower
than java)
[java] interpreted: 52078 iterations in 1000 ms (69.2 times slower
than java)
[java] Property Navigation and Comparison: bean2.bean3.value <= 24
[java] java: 3394879 iterations in 1000 ms
[java] compiled: 68599 iterations in 1000 ms (49.5 times slower
than java)
[java] interpreted: 43283 iterations in 1000 ms (78.4 times slower
than java)
[java] Property Navigation with Indexed Access:
bean2.bean3.indexedValue[25]
[java] java: 3624147 iterations in 1000 ms
[java] compiled: 43374 iterations in 1000 ms (83.6 times slower
than java)
[java] interpreted: 33505 iterations in 1000 ms (108.2 times slower
than java)
[java] Property Navigation with Map Access: bean2.bean3.map["foo"]
[java] java: 2149048 iterations in 1000 ms
[java] compiled: 55539 iterations in 1000 ms (38.7 times slower
than java)
[java] interpreted: 35116 iterations in 1000 ms (61.2 times slower
than java)
Note that the compiled: entries denote the earlier, simpler version of
the Javassist-based compiler that only generated property accessors for
expressions. These tests run for a fixed length of time to test how
many times the statement will be executed.
Although seeing things like "61.2 times slower than java" is a bit
daunting, remember that the last one executed 35,116 times in 1 second.
If you put 100 OGNL expressions of medium complexity in your context it
will be slower, but not noticeably.
> I'm also trying to get my head around how this affects lifecycles and
> when initialization happens. PropertyPlaceholderConfigurer is
> obviously pretty simplistic, all it's going to do is replace a
> placehold value in a text property value with another. It can't
> trigger the initialization of another bean. Now in this OGNL variant,
> if the OGNL script references the context, then it can trigger the
> initialization of other beans, similar in fashion to how a <ref
> bean="xxx"> will trigger the init of that other bean first. Now the
> difference here is that while the <ref bean=""> will trigger that init
> only if used, since this approach is as a bean factory postprocessor
> and all expressions are evaluated at init time, all references beans
> will be immediately initialized at init time. For this reason, while I
> think this is a valid approach, and has the advantage that it doesn't
> require changes to the guts of Spring, I think there's still added
> value in having the idea of expressions known to Spring itself, which
> are only evaluated on demand... Possibly the 2nd step...
Yes, there could be lifecycle issues here that I'm ignorant of. I'm not
as conversant with the internals of Spring as I'd like but my initial
usage has been successful in referencing other beans in the context.
Ideally the OGNL stuff would have the same effect as doing a <ref
bean=""> reference, so that the semantics are consistent.
I chose to implement this as a BeanFactoryPostProcessor instead of some
other approach (like a custom <value>-type tag) because it's less
intrusive and is drop-in compatible. To make it semantically like <ref
bean=""> there might have to be tighter integration. Correct? Or is
the <ref> stuff implemented using the same basic mechanism?
- Drew
--
+---------------------------------+
< Drew Davidson | OGNL Technology >
+---------------------------------+
| Email: dr...@og... /
| Web: http://www.ognl.org /
| Vox: (520) 531-1966 <
| Fax: (520) 531-1965 \
| Mobile: (520) 405-2967 \
+---------------------------------+
|