Benchmarks¶
Three Python packages parse DPM-XL. pydpm-xl and dpmcore validate rules against a DPM database; dpm-xl evaluates rules against report data and explains failures. The table shows where they overlap and where they differ.
Capabilities¶
| dpm-xl | pydpm-xl | dpmcore | |
|---|---|---|---|
| Licence | MIT | GPL-3.0-or-later | Apache-2.0 |
| Runtime dependencies | none | 8 (pandas, SQLAlchemy, database drivers) | antlr4, SQLAlchemy |
| Parses every EBA 3.4–4.4 rule | yes | yes | yes |
| Syntax errors | plain words with position | ANTLR messages | ANTLR messages |
| Evaluates rules against report data | yes | no | no |
| Explains failing records | yes | no | no |
| Columnar evaluation for millions of rows | yes | no | no |
| CLI to evaluate rules on a data file | yes | no | no |
| Tokenizer and editor grammar | yes | no | no |
| Outside dpm-xl's scope: | |||
| Semantic validation against a DPM release | no | yes | yes |
| DPM database migration, REST API | no | migration | yes |
| Reads report files | via dpm-xbrl | no | no |
Use pydpm-xl or dpmcore to check that a rule fits a DPM release; use dpm-xl to check that a report satisfies the rules, and why not. The two combine.
Results¶
The corpus holds the 14,174 distinct rule and precondition expressions of EBA DPM releases 3.4 to 4.4. All three packages reject the same two, which contain typos in the EBA source.
Measured on 2026-10-24 on AMD Ryzen 7 4700U with Radeon Graphics, 8 cores, Linux 7.0.0-38-generic; Python 3.12.3. Best of 3 warm runs; peak RSS over those runs.
Speed and footprint¶
| dpm-xl 1.0.0 | pydpm-xl 0.3.12 | dpmcore 0.2.1 | |
|---|---|---|---|
| Syntax check of the corpus (whole process) | 1.61 s, 23 MB | 14.85 s, 109 MB | 15.23 s, 113 MB |
| Per expression | 113 µs | 1,047 µs | 1,075 µs |
import (whole process) |
0.09 s, 18 MB | 0.75 s, 97 MB | 0.85 s, 101 MB |
| Installed environment | 1 distributions, 1 MB | 17 distributions, 142 MB | 15 distributions, 143 MB |
Coverage of the EBA corpus¶
| dpm-xl 1.0.0 | pydpm-xl 0.3.12 | dpmcore 0.2.1 | |
|---|---|---|---|
| Expressions accepted | 14,172 of 14,174 | 14,172 of 14,174 | 14,172 of 14,174 |
| Rejected | with {default: 0, interval: true}:if sum({tC_08.01.a, r0070…with {tV_03.01, default: null, interval: false}: if not(isn… |
with {default: 0, interval: true}:if sum({tC_08.01.a, r0070…with {tV_03.01, default: null, interval: false}: if not(isn… |
with {default: 0, interval: true}:if sum({tC_08.01.a, r0070…with {tV_03.01, default: null, interval: false}: if not(isn… |
DPM-XL constructs beyond the EBA rules¶
| dpm-xl 1.0.0 | pydpm-xl 0.3.12 | dpmcore 0.2.1 | |
|---|---|---|---|
| rank over a partition | accepted | rejected | accepted |
| windowed aggregate | accepted | rejected | accepted |
| statements with := | accepted | rejected | rejected |
| persistent assignment <- | accepted | rejected | accepted |
| operation reference | accepted | accepted | accepted |
| set operators and literals | accepted | rejected | accepted |
| typed parameter | accepted | rejected | accepted |
| text concatenation & | accepted | accepted | accepted |
| date functions | accepted | rejected | accepted |
| date() and date literals | accepted | rejected | accepted |
| table group | accepted | accepted | accepted |
| annualise | accepted | rejected | accepted |
Syntax error messages¶
{tC_01.00, r0010, c0010} >=
- dpm-xl: expression ends where an operand is expected at position 27
- pydpm-xl: offendingSymbol: [@11,27:26='
',<-1>,1:27] msg: mismatched input ' ' expecting {BOOLEAN_LITERAL, NOT,… - dpmcore: Unexpected error: "offendingSymbol: [@11,27:26='
',<-1>,1:27] msg: mismatched input ' ' expecting {BO…
with {tC_01.00, c0010}: {r0010} = {r0020} +
- dpm-xl: expression ends where an operand is expected at position 43
- pydpm-xl: offendingSymbol: [@21,43:42='
',<-1>,1:43] msg: mismatched input ' ' expecting {BOOLEAN_LITERAL, NOT,… - dpmcore: Unexpected error: "offendingSymbol: [@21,43:42='
',<-1>,1:43] msg: mismatched input ' ' expecting {BO…
Method¶
Each package runs in its own virtual environment from PyPI (dpm-xl from this
repository), as a separate process through its public syntax-check API: one
warm-up, then the best of three runs, with peak memory. Ratios between the
packages are more stable than absolute times. Scripts and instructions are in
benchmarks/.