| # Benchmark
|
|
|
| This benchmark was built by me as part of testing my library and the MQL5 JSON-parsing ecosystem in general, run on my personal development machine.
|
|
|
| ## Reproduction
|
|
|
| ### MQL5 code
|
|
|
| Before anything else, delete the current `.log` file.
|
|
|
| 1. For each test/library, do the following:
|
| - Run `UtilHeader` with the library name.
|
| - Run the test several times in **Parse** mode.
|
| - Recompile the test in **Access** mode.
|
| - Run it several times again.
|
| - Repeat for the next test.
|
| 2. Once all tests are done, run the `UtilFinish` script. It parses the `.log` file (with timestamps) and saves the Parse results into the `.db` file. Access results are saved automatically as they run.
|
|
|
| ### Code in other languages
|
|
|
| Requirements:
|
| - VSCode (optional)
|
| - Python 3.11+
|
| - Rust
|
| - C++ (Visual Studio, or GCC — instructions below assume Visual Studio; with GCC you would need to adapt the `CMakeLists.txt` and the `.h`/`.cpp` files under `DLL` and `BenOther/`)
|
| - The `JsonParserByLeo` repo cloned with all its dependencies (assumed already done at this point)
|
|
|
| 1. **C++**: this was built with Visual Studio 2026 (used for the `simdjson` test as an example). Open the `BenOther/C++` folder as a project, then `Ctrl+S` to let the CMake cache build. After that, compiling produces a `Test.exe` under `out/build/...`.
|
| 2. **Rust**: VSCode was used with the rust-analyzer extension; opening the project pulls dependencies automatically. Then, via CLI:
|
| ```bash
|
| cargo build --release
|
| ```
|
| Run the resulting executable from `target/`. This can all be done purely via CLI too — the above is just the workflow used here; if you know Rust better, feel free to do it differently. Rust knowledge here is basic — just enough to run `sonic-rs`, `serde_json`, etc. The benchmark was the only use case.
|
| 3. **Python**: simplest of all — just have Python installed. VSCode's Run button was used here. A standalone `.exe` can also be generated if preferred.
|
|
|
| ## Performance
|
|
|
| ### Parsing
|
|
|
| Benchmark: `twitter.json` (616.7 KB), 1000 iterations. Values below are total time across all 1000 iterations, sorted fastest to slowest.
|
|
|
| > **Note on the benchmark below:** `JsonParserByLeo` (SIMD) is not validating the input as strictly as `simdjson` does — notably,
|
| it does not perform full UTF-8 validation during the structural scan, and it's a single flat `switch`-based pipeline with no public error-recovery API surface, unlike `simdjson::dom::parser`.
|
| The timings below reflect the work each parser actually does, not a strict apples-to-apples "same guarantees" comparison — read it as "same ballpark, different tradeoffs," not "beats simdjson at its own game."
|
|
|
|
|
| | Parser | Language | Time (ms, total / 1000 iter) |
|
| |--------|----------|-------------------------------|
|
| | **JsonParserByLeo** (with SIMD, via DLL) | MQL5 / C++ DLL | **336-337** |
|
| | **simdjson::dom::parser** (reused parser) | C++ | **380-384** |
|
| | **sonic-rs** (typed struct) | Rust | **460-461** |
|
| | **simdjson.Parser** (reused parser) | Python | **475** |
|
| | **JsonParserByLeo** (single array copy) | MQL5 | **520-521** |
|
| | serde_json (typed struct) | Rust | 788-796 |
|
| | YamlParserByLeo, single array copy | MQL5 | 899-900 |
|
| | simd-json (typed struct) | Rust | 915-972 |
|
| | Claude Fable 5 (Effort=Max), generated code (fast JSON lib), single array copy, 3+ iterations with feedback | MQL5 | 1063.04 |
|
| | FastJson v3.7, single array copy | MQL5 | 1213.43 |
|
| | GLM 5.2 (Max, deep thinking), generated code (fast JSON lib), single array copy, 14+ iterations with feedback | MQL5 | 1249.76 |
|
| | orjson | Python | 1863 |
|
| | ryml (pure parse time) | C++ | 2846.55 |
|
| | simdjson.Parser + as_dict | Python | 4309 |
|
| | ToyJson3, single string copy, tokenization only | MQL5 | 4418.49 |
|
| | simdjson.loads | Python | 4955 |
|
| | ujson | Python | 5322 |
|
| | json (stdlib) | Python | 5860 |
|
| | MQL5-JsonLib (ding9736), single string copy, tape parsing only (no DOM built) | MQL5 | 17547.38 |
|
| | JAson, single array copy | MQL5 | 21118.68 |
|
| | CJsonNode (MQL5 Articles reference implementation), single array copy | MQL5 | 86409.04 |
|
|
|
|
|
| ### Access benchmarks
|
|
|
| All access benchmarks use `test.json`, 1000 iterations, and report total time across all iterations in microseconds. Lower is better. Results are sorted fastest to slowest within each table.
|
|
|
| #### Access — Wide object (100 keys)
|
|
|
| Repeated key lookups across a flat object with 100 keys (random).
|
|
|
| | Parser | Language | Time (microseconds, total / 1000 iter) |
|
| |--------|----------|-------------------------------|
|
| | **JsonParserByLeo** | MQL5 | **112** |
|
| | YamlParserByLeo | MQL5 | 142 (falta revisar) |
|
| | MQL5-JsonLib | MQL5 | 235 |
|
| | Claude Fable 5 (Effort=Max), generated code (fast JSON lib), single array copy, 3+ iterations with feedback | MQL5 | 308 |
|
| | ToyJson3 | MQL5 | 333 |
|
| | FastJson v3.7 | MQL5 | 385 |
|
| | JAson | MQL5 | 460 |
|
| | CJsonNode (MQL5 Articles reference implementation) | MQL5 | 523 |
|
| | GLM 5.2 (Max, deep thinking), generated code | MQL5 | 8826 |
|
|
|
| #### Access — Large array (10K integer elements)
|
|
|
| Sequential/indexed access across a 10,000-element integer array.
|
|
|
| | Parser | Language | Time (microseconds, total / 1000 iter) |
|
| |--------|----------|-------------------------------|
|
| | **JsonParserByLeo** | MQL5 | **104** |
|
| | YamlParserByLeo | MQL5 | 115 |
|
| | CJsonNode (MQL5 Articles reference implementation) | MQL5 | 254 |
|
| | JAson | MQL5 | 267 |
|
| | ToyJson3 | MQL5 | 373 |
|
| | MQL5-JsonLib | MQL5 | 384 |
|
| | Claude Fable 5 (Effort=Max), generated code (fast JSON lib), single array copy, 3+ iterations with feedback | MQL5 | 9758 |
|
| | GLM 5.2 (Max, deep thinking), generated code | MQL5 | 15550 |
|
| | FastJson v3.7 | MQL5 | 16414 |
|
|
|
| #### Access — Deep access
|
|
|
| Access through deeply nested object/array paths.
|
|
|
| | Parser | Language | Time (microseconds, total / 1000 iter) |
|
| |--------|----------|-------------------------------|
|
| | **ToyJson3** | MQL5 | **117** |
|
| | CJsonNode (MQL5 Articles reference implementation) | MQL5 | 227 |
|
| | JAson | MQL5 | 387 |
|
| | JsonParserByLeo | MQL5 | 573 |
|
| | YamlParserByLeo | MQL5 | 755 (falta revisar) |
|
| | Claude Fable 5 (Effort=Max), generated code (fast JSON lib), single array copy, 3+ iterations with feedback | MQL5 | 912 |
|
| | MQL5-JsonLib | MQL5 | 982 |
|
| | FastJson v3.7 | MQL5 | 2236 |
|
| | GLM 5.2 (Max, deep thinking), generated code | MQL5 | 2522 |
|
|
|
| #### Access — Mixed trading-data access pattern
|
|
|
| A mixed read pattern modeled on typical trading-data access (combination of key lookups, array indexing, and nested paths).
|
|
|
| | Parser | Language | Time (microseconds, total 500 iterations) |
|
| |--------|----------|-------------------------------|
|
| | JAson | MQL5 | 543 |
|
| | CJsonNode (MQL5 Articles reference implementation) | MQL5 | 658 |
|
| | ToyJson3 | MQL5 | 928 |
|
| | Claude Fable 5 (Effort=Max), generated code (fast JSON lib), single array copy, 3+ iterations with feedback | MQL5 | 930 |
|
| | MQL5-JsonLib | MQL5 | 984 |
|
| | JsonParserByLeo | MQL5 | 1854 |
|
| | YamlParserByLeo | MQL5 | 2258 (falta revisar) |
|
| | FastJson v3.7 | MQL5 | 2754 |
|
| | GLM 5.2 (Max, deep thinking), generated code | MQL5 | 5894 |
|
|
|
|
|
| #### Serialization
|
| Serialization of (test.json) using the files from the previous tests
|
| | Parser | Language | Time (ms, total / 1000 iter) |
|
| |--------|----------|-------------------------------|
|
| | FastJson v3.7 | MQL5 | 555 |
|
| | JsonParserByLeo (DOM mode - with pointers, etc..) | MQL5 | 750 |
|
| | JAson | MQL5 | 194068.9 (Caution: must be revised) |
|
| | MQL5-JsonLib | MQL5 | 4503261.352 (Caution: must be revised) |
|
|
|
| ## Machine
|
|
|
| - OS Name: Microsoft Windows 10 Pro
|
| - Version: 10.0.19045 Build 19045
|
| - OS Manufacturer: Microsoft Corporation
|
| - System Manufacturer: LENOVO
|
| - System Model: 81DE
|
| - System Type: x64-based PC
|
| - System SKU: LENOVO_MT_81DE_BU_idea_FM_ideapad 330-15IKB
|
| - Processor: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz, 1800 MHz, 4 Cores, 8 Logical Processors
|
| - RAM Type (Form Factor): SODIMM
|
| - RAM Speed: 2133 MHz
|
| - Installed Physical Memory (RAM): 8.00 GB
|
| - Total Physical Memory: 7.91 GB
|
| - Available Physical Memory: 2.87 GB
|
| - Total Virtual Memory: 15.2 GB
|
| - Available Virtual Memory: 9.13 GB
|
| - Page File Space: 7.25 GB
|
| - Storage: 13 GB Intel MEMPEI1J016GAL SSD, 224 GB HP SSD S650 240GB SSD
|
| - Graphics Card: AMD Radeon(TM) 530 (2 GB), Intel(R) UHD Graphics 620 (128 MB)
|
|
|
| ## Performance notes
|
|
|
| - MQL5 runs: MetaTrader 5 x64, build 5836-6070.
|
| - Python/C++/Rust runs: same machine (Python 3.10.9).
|
| - C++ compiled with optimizations (`/O2` in MSVC).
|
| - Rust compiled with maximum optimization (`target=native`, LTO, `opt-level=3`, etc.).
|
|
|
| ## Auditing the results
|
|
|
| The complete `.db` file and the raw `.log` file used to produce it are included in the repository releases, for anyone who wants to independently audit or reproduce these numbers.
|