Just as a quick update. I realized my tests weren't insulated from other code running and create a separate unit test to get performance. The results are now:

        Retrieving from a JavaBean property (user.age) 0ms
        Retrieving from a field (user.age) 0ms
        Retrieving from a JavaBean property (user.address['home'].zipcode) 0ms
        Retrieving from a field (user.address['home'].zipcode) 0ms

        Setting a JavaBean property (user.age) 0ms
        Setting a field (user.age) 0ms
        Setting a JavaBean property (user.address['home'].zipcode) 0ms
        Setting a field (user.address['home'].zipcode) 0ms

I also ran a test setting the address zipcode field 50 times, which is about the highest number of HTTP parameters I could envision and that was 2ms.

Here's the code:

    public void testPerformance() {
        // Set cases

        Object action = new ActionField();
        long start = System.currentTimeMillis();
        evaluator.setValue("user.age", action, array("32"), null);
        long end = System.currentTimeMillis();
        System.out.println("Setting field time was " + (end - start));

        start = System.currentTimeMillis();
evaluator.setValue("user.addresses['home'].zipcode", action, array("80020"), null);
        end = System.currentTimeMillis();
        System.out.println("Setting field time was " + (end - start));

        action = new Action();
        start = System.currentTimeMillis();
        evaluator.setValue("user.age", action, array("32"), null);
        end = System.currentTimeMillis();
System.out.println("Setting property time was " + (end - start));

        start = System.currentTimeMillis();
evaluator.setValue("user.addresses['home'].zipcode", action, array("80020"), null);
        end = System.currentTimeMillis();
System.out.println("Setting proeprty time was " + (end - start));

        // Get cases

        action = new ActionField();
        start = System.currentTimeMillis();
        evaluator.getValue("user.age", action);
        end = System.currentTimeMillis();
        System.out.println("Getting field time was " + (end - start));

        start = System.currentTimeMillis();
        evaluator.getValue("user.addresses['home'].zipcode", action);
        end = System.currentTimeMillis();
        System.out.println("Getting field time was " + (end - start));

        action = new Action();
        start = System.currentTimeMillis();
        evaluator.getValue("user.age", action);
        end = System.currentTimeMillis();
System.out.println("Getting property time was " + (end - start));

        start = System.currentTimeMillis();
        evaluator.getValue("user.addresses['home'].zipcode", action);
        end = System.currentTimeMillis();
System.out.println("Getting property time was " + (end - start));

        // Loop

        start = System.currentTimeMillis();
        for (int i = 0; i < 50; i++) {
evaluator.getValue("user.addresses['home'].zipcode", action);
        }
        end = System.currentTimeMillis();
        System.out.println("50 times was " + (end - start));
    }

And the output:

    [junit] Setting field time was 0
    [junit] Setting field time was 0
    [junit] Setting property time was 0
    [junit] Setting proeprty time was 0
    [junit] Getting field time was 0
    [junit] Getting field time was 0
    [junit] Getting property time was 0
    [junit] Getting property time was 0
    [junit] 50 times was 2

That's definitely fast enough for any web application.

-bp

On Oct 12, 2008, at 11:46 AM, Chris Brock wrote:


Well, I'd like to see an actual comparison. I somehow doubt your parser, which I note is using StringTokenizer will perform as well as MVEL's parser,
which is a much more computationally efficient sliding-window parser.


Brian Pontarelli wrote:

Right, but you can receive similar or better performance using a
linear runtime evaluation if the language is simple enough and tuned
for the web. And as you and I say, MVEL and most other languages
aren't targeted to the web and have many extra features.

I can't really believe that JUEL is that slow though. And if it really is, it should be extremely simple to make it just as fast as MVEL. But
I couldn't say for certain because I don't know the code.

I ran some simple tests on getting and setting properties for the
JCatapult expression evaluator and here's what I got:

Retrieving from a JavaBean property ("user.age")   1ms
Retrieving from a public member field ("user.age")   < 1ms
Retrieving from a nested JavaBean property within a collection
("user.addresses['home'].zipcode")   1ms
Retrieving from a nested public member field within a collection
("user.addresses['home'].zipcode")   1ms

Setting a JavaBean property with type conversion ("user.age")   1ms
Setting a nested JavaBean property, with collections and Object
creation ("user.addresses['home'].zipcode")   2ms

That's definitely fast enough for my web applications. ;)

JCatapult does support using public member fields of classes and it
does shave a little bit of time, but nothing that would make a huge
difference. These are all runtime parsing and handling, nothing is
compiled or cached.

-bp

On Oct 11, 2008, at 3:09 PM, Chris Brock wrote:


The singleton pattern is used in MVEL, with knowledge of the
tradeoff.  MVEL
has a strong emphasis on maintaining interpreted-mode performance.

MVEL contains two runtime systems: an interpreter, and a compiler/
runtime.
Unlike other ELs, MVEL does not simply bootstrap the compiler, and
execute
that way.  Instead, MVEL has a real-time interpreter which evaluates
to a
stack during parsing.  Therefore, the general design decisions,
particularly
around extendability tend to favor singleton-patterns, instead of
heavyweight configuration sessions which would completely bog down the
performance.

http://artexpressive.blogspot.com/2007/11/juel-vs-mvel.html

For an example of how performant MVEL's interpreter is with no factory
caching.

In a simple property expression, with no caching (so parsing before
executing every time), MVEL was able to parse/reduce the expression
"foo.bar" 100,000 times in 94ms. It took JUEL 2749ms to do the same.

Compiled performance was: 5.8ms to 34.2ms in favor of MVEL too.

So I would err on the side of performance here.  If that doesn't cut
it for
web applications, I guess that's fine.  I don't really target MVEL
towards
web applications, really.



Brian Pontarelli wrote:

Taking a brief look at the MVEL type conversion API it could be
somewhat difficult to get this information into the converter on a
per
request basis, especially if converters are singleton scoped. This
information isn't available on the source in most cases. It is
usually
externalized in the request or the container object. The API looks a pretty lightweight, which is nice, but also restrictive. From what I could see I would have to monkey around with things and use something
like a ThreadLocal to pass this information to the converter.

The source-from-many pattern seems to be somewhat backwards for the
web. It is more likely the case that a single converter will convert
to many classes from a String or String[]. The JCatapult type
converter passes in the type being converted to and then the String
value(s). Although this is very web centric, it cleans up the API and
makes things simpler to implement. MVEL is obviously more generic,
which means some massaging is necessary to tune it for the web.

It also seems to be lacking a good set of exceptions thrown out of
the
API. At least from the docs, since I couldn't find JavaDoc and the
distribution only has source (ouch). This doesn't mean that Struts
can't provide good runtime exceptions and then just catch those, but
it leaves things much more open for developers writing new
converters.
I'd rather see the API define these exceptions clearly and for them
to
be checked.

I think that using generic languages like OGNL or MVEL are decent
solutions, but a web centric solution would be best. I'm also in
favor
or dropping most if not all of the extra features and only providing
property/field getting and setting. I think adding in another
language
just clouds the waters. FreeMarker and JSP both have languages that
cover most of the common cases.

Feel free to take a look at the JCatapult MVC expression evaluator
for
what I feel should be supported.

-bp


On Oct 11, 2008, at 12:52 PM, Chris Brock wrote:


MVEL has a pluggable type-conversion API, just like OGNL.  Since
it's
source-from-many in it's design, you can easily design converters
that
perform as much introspection as necessary to determine formatting,
etc.



Brian Pontarelli wrote:

Yeah. That's good. The last thing I would toss in as criteria is a
good type conversion interface. In JCatapult, I actually took
things a
step further. I found that complex types usually needed more
information than just the data to perform the type conversion. For
example, conversion of dates generally requires the date format.
Likewise, conversion to money generally requires the currency code.
In
many MVCs this information is statically configured for the entire
application, configured per action in XML or properties files or
fixed
and not configurable at all.

For maximum flexibility, I built a system where tags could provide
this additional data via extra attributes (it can also be
configured
application wide as well). My tags look like this:

[EMAIL PROTECTED] name="user.lifeSavings" currencyCode="USD"/]
[EMAIL PROTECTED] name="user.birthDay" dateTimeFormat="MM/dd/yyyy"/]

This information then gets passed to the type converters as part of
the API.

This then reveals another shortcoming of OGNL and the wrapper in
Struts, what if a required attribute is missing? This is a
different
case then if the type conversion fails. So, I created two distinct
checked exceptions to handle these two cases. This makes the type
conversion system more powerful and easy to interact with. Plus, it
reveals good exceptions for coding problems.

-bp

On Oct 10, 2008, at 3:00 AM, Chris Brock wrote:


MVEL will handle type coercion for method parameters, properties,
and even on
egress of those values if the generic type information can be
deduced on
ingress.  In situtations where the generic type is dependent on
the
root of
the object graph though, MVEL cannot infer generic type data
(ie. a
bound
variable, that's say a Map) because of erasure.  There is no
generic
type
information held on a per-instance basis.

However, if the parameterized type is a class member say:

class Foo {
public Map<String, Integer> map;
}

And you use an instance of Foo as a context or as a bound
variable,
MVEL's
compiler can certainly extract the generic type information, and
provide
automatic coercion and verification accordingly.  MVEL's type
verifier will
always extrapolate whatever type data is available.



Brian Pontarelli wrote:

This is not quite the same unless it can detect generics while
setting
values and creating values. An example might be values from a
form
going into something like:

        List<String>

or

        Map<String, List<Integer>>

or the always fun

        List<List<Integer>>

that sorta thing. I know that OGNL had (might not any longer)
many
issues with generics in this respect. I think OGNL also got mad
when
it encountered something simple like:

        int[]

or

        String[]

coming from checkbox lists and multiple selects. I believe that
it
would stuff the values into the String[] like this:

        {"value1,value2,value3"}

rather than

        {"value1", "value2", "value3"}

This was a while ago, so all of this might be fixed.

-bp


On Oct 9, 2008, at 7:32 PM, Chris Brock wrote:


MVEL 2.0 has full support for generics (and static typing):
http://mvel.codehaus.org/Strong+Typing+Mode


Brian Pontarelli wrote:


On Oct 7, 2008, at 3:08 PM, Dave Newton wrote:

Just to muddy the EL/templating waters:

http://mvel.codehaus.org/Performance+of+MVEL

(v. OGNL)

Not sure about MVEL or OGNL at this point, but everything was
lacking
in support for generics, collections and arrays. I wrote my own
for
the JCatapult MVC and it was really not all that hard. It only
handles
getting and setting, but I figure that's all that should be
allowed
at
that point anyways.

-bp


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



--
View this message in context:
http://www.nabble.com/MVEL--tp19867360p19910418.html
Sent from the Struts - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



--
View this message in context:
http://www.nabble.com/MVEL--tp19867360p19914597.html
Sent from the Struts - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



--
View this message in context:
http://www.nabble.com/MVEL--tp19867360p19935345.html
Sent from the Struts - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



--
View this message in context:
http://www.nabble.com/MVEL--tp19867360p19936453.html
Sent from the Struts - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



--
View this message in context: 
http://www.nabble.com/MVEL--tp19867360p19943987.html
Sent from the Struts - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to