Print
Performance of MVEL 2.0

MVEL 2.0 continues in the tradition of MVEL 1.2/1.3 of going for high performance expression evaluation.

Comparisons

The above graph (click it to enlarge) demonstrates the performance differences for some simple benchmarks applied against other popular embeddable scripting languages.

Shorter bars mean higher performance.

The No Cache values indicate performance with no caching, or re-use of resources such as resolvers, factories, etc. Each iteration in this category represents a cold start of the parser, all the way to the result of the expression. In MVEL's case, this is generally referred to as interpreted performance. The performance of the libraries in this respect can generally be used to evaluate how efficiently they actually parse the expression.

The Cache values indicate performance with caching, including reuse of any resolvers or factories that would normally be used. This may not be reflective of real-world performance, as it may not be practical to maintain cache of variable resolvers over a long period of time. But the benchmark allows for this none the less.

For these tests, MVEL and Groovy were the only implementations capable of running the Compiled tests. The compiled tests measure performance with bytecode generation. Although OGNL 2.7.2 supports bytecode generation, it only supports bytecode generation against root context objects. All of these tests took advantage of variable injection, and therefore it was not possible to test OGNL's Javassist bytecode compiler.

Groovy was not tested for No Cache values. This is because Groovy's compiler is too slow to reasonably test. 25,000 compiles in Groovy took in excess of 5 minutes. Interestingly, the compiled tests for Groovy yielded slower performance than both MVEL and JEXL. The compiled test for Groovy used the same groovy.lang.Script Object for each iteration, and did not re-inject variables.

Results and Observations

MVEL has the fastest parser and compiler, by far.

MVEL outperforms all other implementations on all benchmarks except for the arithmetic performance benchmark where JEXL and MVEL are tied (12ms for 50,000 iterations).

Groovy has the slowest compiler, followed by JUEL and then OGNL.

OGNL has the worst cached performance for reflection, followed by JEXL.

OGNL has the worst performance for the nested map benchmark. This benchmark involves resolving a property from within a Map using the indexer syntax (foo['bar']['something']).

Groovy's compiler is far too slow to use in an ad hoc way.

Raw Result Data

Test Group: foo.bar.name (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 1633
OGNL 2.7.2 [Cached]: Average ms: 181
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 540
JEXL 1.1 [Cached]: Average ms: 121
JEXL 1.1 [Compiled]: Not Supported
JUEL 2.1.0 [No Cache]: Average ms: 2895
JUEL 2.1.0 [Cached]: Average ms: 52
JUEL 2.1.0 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Average ms: 34
Groovy 1.5.7 [Compiled]: Not Supported
MVEL 2.0 [No Cache]: Average ms: 127
MVEL 2.0 [Cached]: Average ms: 12
MVEL 2.0 [Compiled]: Average ms: 6

Test Group: x + y * z (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 1530
OGNL 2.7.2 [Cached]: Average ms: 66
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 523
JEXL 1.1 [Cached]: Average ms: 12
JEXL 1.1 [Compiled]: Not Supported
JUEL 2.1.0 [No Cache]: Average ms: 2908
JUEL 2.1.0 [Cached]: Average ms: 61
JUEL 2.1.0 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Average ms: 39
Groovy 1.5.7 [Compiled]: Not Supported
MVEL 2.0 [No Cache]: Average ms: 161
MVEL 2.0 [Cached]: Average ms: 12
MVEL 2.0 [Compiled]: Average ms: 15

Test Group: foo['bar']['something'] (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 1596
OGNL 2.7.2 [Cached]: Average ms: 75
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 680
JEXL 1.1 [Cached]: Average ms: 11
JEXL 1.1 [Compiled]: Not Supported
JUEL 2.1.0 [No Cache]: Average ms: 2889
JUEL 2.1.0 [Cached]: Average ms: 39
JUEL 2.1.0 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Not Supported
Groovy 1.5.7 [Compiled]: Average ms: 35
MVEL 2.0 [No Cache]: Average ms: 144
MVEL 2.0 [Cached]: Average ms: 8
MVEL 2.0 [Compiled]: Average ms: 5

Update: New Performance Comparisons for MVEL 2.0.14

Test Group: foo.bar.name (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 2024
OGNL 2.7.2 [Cached]: Average ms: 277
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 678
JEXL 1.1 [Cached]: Average ms: 163
JEXL 1.1 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Average ms: 35
Groovy 1.5.7 [Compiled]: Not Supported
MVEL 2.0 [No Cache]: Average ms: 192
MVEL 2.0 [Cached]: Average ms: 7
MVEL 2.0 [Compiled]: Average ms: 1

Test Group: x + y * z (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 2131
OGNL 2.7.2 [Cached]: Average ms: 73
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 646
JEXL 1.1 [Cached]: Average ms: 12
JEXL 1.1 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Average ms: 56
Groovy 1.5.7 [Compiled]: Not Supported
MVEL 2.0 [No Cache]: Average ms: 401
MVEL 2.0 [Cached]: Average ms: 4
MVEL 2.0 [Compiled]: Average ms: 7

Test Group: foo['bar']['something'] (iterations: 25000)
OGNL 2.7.2 [No Cache]: Average ms: 1560
OGNL 2.7.2 [Cached]: Average ms: 76
OGNL 2.7.2 [Compiled]: Not Supported
JEXL 1.1 [No Cache]: Average ms: 671
JEXL 1.1 [Cached]: Average ms: 13
JEXL 1.1 [Compiled]: Not Supported
Groovy 1.5.7 [No Cache]: Not Supported
Groovy 1.5.7 [Cached]: Average ms: 42
Groovy 1.5.7 [Compiled]: Not Supported
MVEL 2.0 [No Cache]: Average ms: 231
MVEL 2.0 [Cached]: Average ms: 5
MVEL 2.0 [Compiled]: Average ms: 2
Powered by Atlassian Confluence