From 4883a6508a8539dd032f6c92247037e669d6c444 Mon Sep 17 00:00:00 2001 From: Vinit Kumar Date: Wed, 12 Aug 2026 15:34:40 +0530 Subject: [PATCH 1/2] fix: use python 3.15 rc1 --- .github/workflows/pythonpackage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index bd5d2788..5e99c213 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -33,7 +33,7 @@ jobs: matrix: # Pin PyPy 3.11 to the 7.3.23 build so CI keeps exercising the # CPython 3.11.15-compatible runtime documented in BENCHMARKS.md. - python-version: [pypy-3.10, pypy-3.11-v7.3.23, '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t', '3.15.0-beta.3'] + python-version: [pypy-3.10, pypy-3.11-v7.3.23, '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t', '3.15.0-rc.1'] os: [ ubuntu-latest, windows-latest, From 3519c968d3aabf1d0119ef51284ccc4dcfbaa74e Mon Sep 17 00:00:00 2001 From: Vinit Kumar Date: Wed, 12 Aug 2026 15:40:26 +0530 Subject: [PATCH 2/2] fix: use python 3.15 rc1 --- lat.md/architecture.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lat.md/architecture.md b/lat.md/architecture.md index 9765e298..1cc3e98b 100644 --- a/lat.md/architecture.md +++ b/lat.md/architecture.md @@ -54,15 +54,15 @@ Reproduction docs require contributors to record machine, OS, Python, and tool a The June 2026 Rust memory benchmark uses [[benchmark_memory_rust.py#main]] under hyperfine to compare release builds in fresh Python processes. The bytes-writer implementation cuts serializer peak RSS by about half for large outputs, with a documented throughput tradeoff. -The June 2026 multi-interpreter CLI rerun uses [[benchmark_multi_python.py#main]] with per-interpreter virtual environments. On the recorded Apple Silicon run, CPython 3.15.0b3 beat CPython 3.14.6 on every case, PyPy 3.11.15 only won the largest case, and Go remained the fastest end-to-end CLI path overall. +The June 2026 multi-interpreter CLI rerun uses [[benchmark_multi_python.py#main]] with per-interpreter virtual environments. On the recorded Apple Silicon run, CPython 3.15.0rc1 beat CPython 3.14.6 on every case, PyPy 3.11.15 only won the largest case, and Go remained the fastest end-to-end CLI path overall. The Rust serializer's bytes-writer hot path uses monomorphized `Write` helpers and a bounded 16 KiB buffer instead of dynamic dispatch and one output write per XML fragment, reducing CPU overhead while retaining direct output into the final Python bytes object and its lower peak-memory profile. A controlled CPython 3.14 benchmark improved a 5,000-record payload from roughly 4.8 ms to 2.4 ms median while keeping the 100,000-record serializer delta near 80 MiB. -The benchmark script now tracks uv-managed current-series interpreters through a configurable `JSON2XML_UV_PYTHON_DIR` base path plus per-interpreter overrides, with the documented defaults targeting CPython 3.14.6, CPython 3.15.0b3, and PyPy 3.11.15. That keeps the published setup reproducible without hard-coding one contributor's home directory. +The benchmark script now tracks uv-managed current-series interpreters through a configurable `JSON2XML_UV_PYTHON_DIR` base path plus per-interpreter overrides, with the documented defaults targeting CPython 3.14.6, CPython 3.15.0rc1, and PyPy 3.11.15. That keeps the published setup reproducible without hard-coding one contributor's home directory. -The July 2026 CPython 3.15.0b3 flamegraph for a 5,000-record nested payload identified repeated abstract type dispatch inside [[json2xml/dicttoxml.py#_append_convert_dict]] as the pure-Python bottleneck. Exact JSON-native type paths now precede compatibility fallbacks, while [[json2xml/dicttoxml.py#_is_number]] preserves `Decimal`, `Fraction`, complex, and custom `Number` support. The fixed workload improved from 83.0 ms to 57.2 ms per conversion; a 20-loop tracing profile fell from 8.311 s and 48.17 million calls to 5.782 s and 30.13 million calls. The committed [before](../docs/flamegraphs/python315-before.svg) and [after](../docs/flamegraphs/python315-after.svg) flamegraphs preserve the call-tree evidence. +The July 2026 CPython 3.15.0rc1 flamegraph for a 5,000-record nested payload identified repeated abstract type dispatch inside [[json2xml/dicttoxml.py#_append_convert_dict]] as the pure-Python bottleneck. Exact JSON-native type paths now precede compatibility fallbacks, while [[json2xml/dicttoxml.py#_is_number]] preserves `Decimal`, `Fraction`, complex, and custom `Number` support. The fixed workload improved from 83.0 ms to 57.2 ms per conversion; a 20-loop tracing profile fell from 8.311 s and 48.17 million calls to 5.782 s and 30.13 million calls. The committed [before](../docs/flamegraphs/python315-before.svg) and [after](../docs/flamegraphs/python315-after.svg) flamegraphs preserve the call-tree evidence. -The July 2026 native Rust flamegraph identified the scalar byte loop in the XML escape writer as the largest avoidable Rust cost. The shared scanner now uses `memchr` word/SIMD search for the five XML escape bytes and copies clean UTF-8 spans in bulk without changing the bounded bytes writer. A bounded sparse fast path switches to monotonic scanners after four matches, retaining normal-payload speed while keeping dense escape input linear. On the same deterministic 5,000-record CPython 3.15.0b3 workload, paired release medians improved from 6.007 ms to 5.632 ms per conversion, or 6.23%, while the escape writer's exclusive native sample share fell from 14.31% to 7.97%. A follow-up 4–128 KiB capacity sweep retained the 16 KiB buffer: the stable range plateaued at 16–64 KiB, and an interleaved confirmation measured 16 KiB about 0.8% faster than 32 KiB without extra per-call memory. The committed [Rust before](../docs/flamegraphs/rust-before.svg) and [Rust after](../docs/flamegraphs/rust-after.svg) flamegraphs preserve the symbolized native-stack evidence. +The July 2026 native Rust flamegraph identified the scalar byte loop in the XML escape writer as the largest avoidable Rust cost. The shared scanner now uses `memchr` word/SIMD search for the five XML escape bytes and copies clean UTF-8 spans in bulk without changing the bounded bytes writer. A bounded sparse fast path switches to monotonic scanners after four matches, retaining normal-payload speed while keeping dense escape input linear. On the same deterministic 5,000-record CPython 3.15.0rc1 workload, paired release medians improved from 6.007 ms to 5.632 ms per conversion, or 6.23%, while the escape writer's exclusive native sample share fell from 14.31% to 7.97%. A follow-up 4–128 KiB capacity sweep retained the 16 KiB buffer: the stable range plateaued at 16–64 KiB, and an interleaved confirmation measured 16 KiB about 0.8% faster than 32 KiB without extra per-call memory. The committed [Rust before](../docs/flamegraphs/rust-before.svg) and [Rust after](../docs/flamegraphs/rust-after.svg) flamegraphs preserve the symbolized native-stack evidence. ## Dependency security @@ -80,7 +80,7 @@ Dependabot checks the root and documentation Python dependency manifests weekly, GitHub Actions workflows run with read-only tokens by default and use full SHA pins so third-party action updates are explicit. -The `.github/workflows/` files declare the minimum `permissions:` scopes needed by each workflow, with CodeQL retaining `security-events: write` for result upload and TestPyPI retaining `id-token: write` for explicit trusted-publishing runs. The Python test job also scopes `id-token: write` and `FLAKINESS_PROJECT` to its pytest matrix so the flakiness reporter can authenticate through GitHub OIDC without exposing that permission to lint. Release-branch pushes build distributions and runs Twine checks; TestPyPI upload is a manual opt-in because that external registry requires separate publisher configuration. Action references are pinned to immutable commits with the upstream tag retained in comments for reviewability, and `.github/dependabot.yml` checks the `github-actions` ecosystem weekly so those pins do not silently age. The Python test matrix pins its PyPy 3.11 job to an explicit PyPy release so CI keeps exercising the intended CPython 3.11.15-compatible runtime instead of silently drifting with runner cache updates. It also exercises regular CPython 3.15.0b3 while leaving that beta's free-threaded builds out of CI until the runner support is less brittle. +The `.github/workflows/` files declare the minimum `permissions:` scopes needed by each workflow, with CodeQL retaining `security-events: write` for result upload and TestPyPI retaining `id-token: write` for explicit trusted-publishing runs. The Python test job also scopes `id-token: write` and `FLAKINESS_PROJECT` to its pytest matrix so the flakiness reporter can authenticate through GitHub OIDC without exposing that permission to lint. Release-branch pushes build distributions and runs Twine checks; TestPyPI upload is a manual opt-in because that external registry requires separate publisher configuration. Action references are pinned to immutable commits with the upstream tag retained in comments for reviewability, and `.github/dependabot.yml` checks the `github-actions` ecosystem weekly so those pins do not silently age. The Python test matrix pins its PyPy 3.11 job to an explicit PyPy release so CI keeps exercising the intended CPython 3.11.15-compatible runtime instead of silently drifting with runner cache updates. It also exercises regular CPython 3.15.0rc1 while leaving that beta's free-threaded builds out of CI until the runner support is less brittle. Rust extension CI triggers on Rust sources, Rust integration tests, and Python fast-path files such as [[json2xml/backend_selector.py]] and [[json2xml/dicttoxml_fast.py]]. That keeps native backend tests attached to the Python dispatch code that decides whether the accelerator is used.