diff --git a/README.md b/README.md
index 69101c78..e31a9d52 100644
--- a/README.md
+++ b/README.md
@@ -24,8 +24,8 @@
- [Is there a `dumps`, `write` or `encode` function?](#is-there-a-dumps-write-or-encode-function)
- [How do TOML types map into Python types?](#how-do-toml-types-map-into-python-types)
- [Performance](#performance)
- - [Pure Python](#pure-python)
- [Mypyc generated wheel](#mypyc-generated-wheel)
+ - [Pure Python](#pure-python)
@@ -156,7 +156,7 @@ tomllib.loads("['This parses fine with Python 3.6+']")
- it's lil'
- pure Python with zero dependencies
- the fastest pure Python parser [\*](#pure-python):
- 18x as fast as [tomlkit](https://pypi.org/project/tomlkit/),
+ 14x as fast as [tomlkit](https://pypi.org/project/tomlkit/),
2.1x as fast as [toml](https://pypi.org/project/toml/)
- outputs [basic data types](#how-do-toml-types-map-into-python-types) only
- 100% spec compliant: passes all tests in
@@ -202,36 +202,32 @@ The core library does not include write capability, as most TOML use cases are r
The `benchmark/` folder in this repository contains a performance benchmark for comparing the various Python TOML parsers.
-Below are the results for commit [0724e2a](https://github.com/hukkin/tomli/tree/0724e2ab1858da7f5e05a9bffdb24c33589d951c).
+Below are the results for commit [064e492](https://github.com/hukkin/tomli/tree/064e492919b2338def788753b8c981c9131334c0).
-### Pure Python
+### Mypyc generated wheel
```console
foo@bar:~/dev/tomli$ python --version
-Python 3.12.7
+Python 3.14.2
foo@bar:~/dev/tomli$ pip freeze
-attrs==21.4.0
-click==8.1.7
-pytomlpp==1.0.13
-qtoml==0.3.1
-rtoml==0.11.0
+pytomlpp==1.1.0
+rtoml==0.13.0
toml==0.10.2
tomli @ file:///home/foo/dev/tomli
-tomlkit==0.13.2
+tomlkit==0.13.3
foo@bar:~/dev/tomli$ python benchmark/run.py
Parsing data.toml 5000 times:
------------------------------------------------------
parser | exec time | performance (more is better)
-----------+------------+-----------------------------
- rtoml | 0.647 s | baseline (100%)
- pytomlpp | 0.891 s | 72.62%
- tomli | 3.14 s | 20.56%
- toml | 6.69 s | 9.67%
- qtoml | 8.27 s | 7.82%
- tomlkit | 56.1 s | 1.15%
+ rtoml | 0.328 s | baseline (100%)
+ pytomlpp | 0.365 s | 89.75%
+ tomli | 0.838 s | 39.12%
+ toml | 3.01 s | 10.90%
+ tomlkit | 20.7 s | 1.59%
```
-### Mypyc generated wheel
+### Pure Python
```console
foo@bar:~/dev/tomli$ python benchmark/run.py
@@ -239,10 +235,9 @@ Parsing data.toml 5000 times:
------------------------------------------------------
parser | exec time | performance (more is better)
-----------+------------+-----------------------------
- rtoml | 0.668 s | baseline (100%)
- pytomlpp | 0.893 s | 74.81%
- tomli | 1.96 s | 34.18%
- toml | 6.64 s | 10.07%
- qtoml | 8.26 s | 8.09%
- tomlkit | 52.9 s | 1.26%
+ rtoml | 0.323 s | baseline (100%)
+ pytomlpp | 0.365 s | 88.40%
+ tomli | 1.44 s | 22.36%
+ toml | 3.03 s | 10.65%
+ tomlkit | 20.6 s | 1.57%
```
diff --git a/benchmark/requirements.txt b/benchmark/requirements.txt
index 24339856..2b613587 100644
--- a/benchmark/requirements.txt
+++ b/benchmark/requirements.txt
@@ -5,5 +5,4 @@
pytomlpp
toml
tomlkit
-qtoml
rtoml
diff --git a/benchmark/run.py b/benchmark/run.py
index 83a406d8..ee88fc5e 100644
--- a/benchmark/run.py
+++ b/benchmark/run.py
@@ -5,7 +5,6 @@
import timeit
import pytomlpp
-import qtoml
import rtoml
import toml
import tomlkit
@@ -22,7 +21,7 @@ def benchmark(
) -> float:
placeholder = "Running..."
print(f"{name:>{col_width[0]}} | {placeholder}", end="", flush=True)
- time_taken = timeit.timeit(func, number=run_count)
+ time_taken = min(timeit.repeat(func, number=run_count, repeat=5))
print("\b" * len(placeholder), end="")
time_suffix = " s"
print(f"{time_taken:{col_width[1]-len(time_suffix)}.3g}{time_suffix}", end="")
@@ -39,9 +38,6 @@ def run(run_count: int) -> None:
data_path = Path(__file__).parent / "data.toml"
test_data = data_path.read_bytes().decode()
- # qtoml has a bug making it crash without this newline normalization
- test_data = test_data.replace("\r\n", "\n")
-
col_width = (10, 10, 28)
col_head = ("parser", "exec time", "performance (more is better)")
print(f"Parsing data.toml {run_count} times:")
@@ -55,7 +51,6 @@ def run(run_count: int) -> None:
benchmark("pytomlpp", run_count, lambda: pytomlpp.loads(test_data), col_width, compare_to=baseline) # noqa: E501
benchmark("tomli", run_count, lambda: tomli.loads(test_data), col_width, compare_to=baseline) # noqa: E501
benchmark("toml", run_count, lambda: toml.loads(test_data), col_width, compare_to=baseline) # noqa: E501
- benchmark("qtoml", run_count, lambda: qtoml.loads(test_data), col_width, compare_to=baseline) # noqa: E501
benchmark("tomlkit", run_count, lambda: tomlkit.parse(test_data), col_width, compare_to=baseline) # noqa: E501
# fmt: on