mirror of
https://github.com/aziascreations/PB-MessagePack.git
synced 2026-11-03 17:01:24 +01:00
9facb66ee8
Co-Authored-By: Claude <noreply@anthropic.com>
118 lines
5.4 KiB
Markdown
118 lines
5.4 KiB
Markdown
# PureBasic - MsgPack - Performances
|
|
Performance benchmarks for the [PB-MessagePack](../readme.md) include.
|
|
|
|
Please refer to the [Performances](../readme.md#performances) section for the warnings and conclusions. \
|
|
Open questions raised by these results are tracked in [Investigations.md](Investigations.md).
|
|
|
|
|
|
## Workloads
|
|
Each folder has a `RunPerfTests.ps1` script that runs its benchmarks:
|
|
* `MassiveReadAmount/` - 1M small fields written, read and skipped, with explicit and implicit typing.
|
|
* `StringsAndBinary/` - Strings of 8 B to 64 KB, and binaries of 1 KB and 1 MB, written and read.
|
|
* `FlatMaps/` - 100K maps of 16 entries written and read.
|
|
* `DeepNesting/` - Arrays nested 1 to 128 levels deep, built, examined and measured. (PureBasic only)
|
|
* `NullChecks/` - Small fields written and read with and without `#MsgPack_DisableNullChecks`. (PureBasic only)
|
|
|
|
The first three are compared to [msgpack](https://pypi.org/project/msgpack/) (Python)
|
|
and [MessagePack-CSharp](https://github.com/MessagePack-CSharp/MessagePack-CSharp) (.NET).
|
|
|
|
The scripts prompt for the PureBasic version, architecture and backend. \
|
|
The results are saved in `Results/`, as one CSV per folder, PureBasic version, architecture and backend.
|
|
|
|
|
|
## Results
|
|
Hardware:
|
|
* Proxmox VM running Windows 10
|
|
* 10 Intel Core i5-13500 cores **(No E/P core pinning)**
|
|
* PureBasic 6.41
|
|
* Python 3.14 with [msgpack](https://pypi.org/project/msgpack/) 1.2.3
|
|
* .NET 10 with [MessagePack-CSharp](https://github.com/MessagePack-CSharp/MessagePack-CSharp) 3.1.12
|
|
|
|
Times are in nanoseconds per field, per map or per nested structure, lower is better. \
|
|
Every implementation produced the same bytes and read back the same values. \
|
|
PureBasic 6.41 is used everywhere, except in the [last table](#purebasic-621-vs-641).
|
|
|
|
### Compared to other implementations
|
|
x64 with the C backend, the fastest of each row in bold.
|
|
|
|
| Workload | Op | PureBasic | Python | .NET |
|
|
|:--|:--|--:|--:|--:|
|
|
| 1M small fields <sup>1</sup> | Write | 11.9 | 50.9 | **5.4** |
|
|
| | Read | 12.7 | 52.4 | **10.6** |
|
|
| | Skip | **18.3** | 40.2 | 29.4 |
|
|
| Strings, 8 B | Write | 59.6 | 62.0 | **13.2** |
|
|
| | Read | 46.6 | 73.4 | **16.2** |
|
|
| Strings, 1 KB | Write | 720.9 | **556.0** | 804.8 |
|
|
| | Read | 570.0 | 341.3 | **150.0** |
|
|
| Strings, 64 KB | Write | 45,917 | **33,932** | 39,848 |
|
|
| | Read | 31,473 | **16,390** | 23,045 |
|
|
| Binary, 1 KB | Write | **190.6** | 556.6 | 576.1 |
|
|
| | Read | **50.2** | 311.3 | 204.0 |
|
|
| Binary, 1 MB | Write | **207,744** | 574,825 | 438,025 |
|
|
| | Read | **54,812** | 465,075 | 59,459 |
|
|
| Maps of 16 entries | Write | 1,793 | 927.2 | **209.2** |
|
|
| | Read | 1,858 | 1,962 | **292.1** |
|
|
|
|
<sup>1</sup> 1M fields of mixed integers, floats and short strings, with implicit typing. PureBasic writes into a preallocated buffer.
|
|
|
|
### Architectures & backends
|
|
PureBasic only.
|
|
|
|
| Scenario | x64 C | x64 ASM | x86 C |
|
|
|:--|--:|--:|--:|
|
|
| Small fields, explicit write | 11.0 | 18.0 | 13.9 |
|
|
| Small fields, explicit read | 9.8 | 15.9 | 8.8 |
|
|
| Small fields, implicit write | 11.9 | 25.4 | 14.2 |
|
|
| Small fields, implicit read | 12.7 | 25.3 | 11.5 |
|
|
| Small fields, skip | 18.3 | 57.9 | 23.2 |
|
|
| Small fields, write, 64 KB growth <sup>2</sup> | 37.9 | 51.5 | 44.7 |
|
|
| Small fields, write, exact growth <sup>2</sup> | 441.0 | 461.6 | 503.3 |
|
|
| Small fields, read, null checks off <sup>3</sup> | 11.4 | 19.5 | 11.4 |
|
|
| Small fields, read, null checks on <sup>3</sup> | 12.2 | 20.2 | 11.4 |
|
|
| Strings, 1 KB UTF-16, write | 526.0 | 539.1 | 599.0 |
|
|
| Strings, 1 KB UTF-16, read | 282.7 | 298.8 | 289.1 |
|
|
| Maps of 16 entries, write | 1,793 | 3,472 | 2,189 |
|
|
| Maps of 16 entries, read | 1,858 | 3,232 | 1,782 |
|
|
|
|
<sup>2</sup> The buffer starts at 64 bytes and grows in multiples of 64 KB, or by the exact size of each write. (`GrowthIncrement` of `1`) \
|
|
<sup>3</sup> With and without `#MsgPack_DisableNullChecks`.
|
|
|
|
### Deep nesting
|
|
x64 with the C backend, arrays of 3 integers nested `N` levels deep.
|
|
|
|
| Depth | Build | Examine | Examine, unsafe | `MsgPackGetFieldFullSize` |
|
|
|--:|--:|--:|--:|--:|
|
|
| 1 | 283.3 | 177.8 | 134.9 | 80.4 |
|
|
| 2 | 453.4 | 363.2 | 261.4 | 115.8 |
|
|
| 4 | 1,002 | 825.2 | 464.1 | 177.3 |
|
|
| 8 | 2,226 | 2,154 | 906.9 | 308.9 |
|
|
| 16 | 6,414 | 6,155 | 1,807 | 546.5 |
|
|
| 32 | 21,888 | 21,134 | 4,367 | 985.9 |
|
|
| 64 | 76,370 | 72,715 | 7,774 | 1,997 |
|
|
| 128 | 278,388 | 269,656 | 15,803 | 3,812 |
|
|
|
|
### PureBasic 6.21 vs 6.41
|
|
x64 with the C backend, the new string handling of 6.40 being the main difference.
|
|
|
|
| Scenario | 6.21 | 6.41 | Speedup |
|
|
|:--|--:|--:|--:|
|
|
| Small fields, implicit write <sup>4</sup> | 23.0 | 11.9 | 1.9x |
|
|
| Small fields, implicit read <sup>4</sup> | 26.4 | 12.7 | 2.1x |
|
|
| Small fields, skip | 14.7 | 18.3 | 0.8x |
|
|
| Strings, 8 B, write | 162.8 | 59.6 | 2.7x |
|
|
| Strings, 8 B, read | 164.5 | 46.6 | 3.5x |
|
|
| Strings, 1 KB, write | 1,971 | 720.9 | 2.7x |
|
|
| Strings, 1 KB, read | 1,412 | 570.0 | 2.5x |
|
|
| Strings, 64 KB, write | 113,872 | 45,917 | 2.5x |
|
|
| Strings, 64 KB, read | 77,056 | 31,473 | 2.4x |
|
|
| Strings, 1 KB UTF-16, write | 2,026 | 526.0 | 3.9x |
|
|
| Strings, 1 KB UTF-16, read | 1,065 | 282.7 | 3.8x |
|
|
| Binary, 1 KB, write | 173.4 | 190.6 | 0.9x |
|
|
| Binary, 1 KB, read | 41.2 | 50.2 | 0.8x |
|
|
| Maps of 16 entries, write <sup>4</sup> | 3,221 | 1,793 | 1.8x |
|
|
| Maps of 16 entries, read <sup>4</sup> | 3,478 | 1,858 | 1.9x |
|
|
| Nested 128 levels, examine | 263,158 | 269,656 | 1.0x |
|
|
|
|
<sup>4</sup> Includes strings, one per record of 8 fields, and one per map key. \
|
|
The x64 ASM and x86 C results show the same 2 to 3 times speedup on strings.
|