|
1 | 1 | # json2xml Benchmark Results |
2 | 2 |
|
3 | | -Comprehensive performance comparison between Python implementations and the Go version of json2xml. |
| 3 | +Comprehensive performance comparison between all json2xml implementations. |
4 | 4 |
|
5 | 5 | ## Test Environment |
6 | 6 |
|
7 | | -- **Machine**: Apple Silicon (aarch64) |
| 7 | +- **Machine**: Apple Silicon (M-series, aarch64) |
8 | 8 | - **OS**: macOS |
9 | | -- **Date**: January 14, 2026 |
| 9 | +- **Date**: January 16, 2026 |
10 | 10 |
|
11 | 11 | ### Implementations Tested |
12 | 12 |
|
13 | | -| Implementation | Version | Notes | |
14 | | -|----------------|---------|-------| |
15 | | -| CPython | 3.14.2 | Homebrew installation | |
16 | | -| CPython | 3.15.0a4 | Latest alpha via uv | |
17 | | -| PyPy | 3.10.16 | JIT-compiled Python | |
18 | | -| Go | 1.0.0 | json2xml-go | |
| 13 | +| Implementation | Type | Notes | |
| 14 | +|----------------|------|-------| |
| 15 | +| Python | Library | Pure Python (json2xml) | |
| 16 | +| Rust | Library | Native extension via PyO3 (json2xml-rs) | |
| 17 | +| Go | CLI | Standalone binary (json2xml-go) | |
| 18 | +| Zig | CLI | Standalone binary (json2xml-zig) | |
19 | 19 |
|
20 | 20 | ## Test Data |
21 | 21 |
|
22 | 22 | | Size | Description | Bytes | |
23 | 23 | |------|-------------|-------| |
24 | 24 | | Small | Simple object `{"name": "John", "age": 30, "city": "New York"}` | 47 | |
25 | | -| Medium | `bigexample.json` (patent data) | 2,598 | |
26 | | -| Large | 1,000 generated records with nested structures | 323,130 | |
27 | | -| Very Large | 5,000 generated records with nested structures | 1,619,991 | |
| 25 | +| Medium | 10 generated records with nested structures | 3,212 | |
| 26 | +| bigexample.json | Real-world patent data | 2,018 | |
| 27 | +| Large | 100 generated records with nested structures | 32,226 | |
| 28 | +| Very Large | 1,000 generated records with nested structures | 323,126 | |
28 | 29 |
|
29 | 30 | ## Results |
30 | 31 |
|
31 | | -### Individual Test Results |
| 32 | +### Performance Summary |
32 | 33 |
|
33 | | -| Test | CPython 3.14.2 | CPython 3.15.0a4 | PyPy 3.10.16 | Go | |
34 | | -|------|----------------|------------------|--------------|-----| |
35 | | -| **Small JSON** (47 bytes) | 75.46ms | 55.74ms (**1.4x faster**) | 121.47ms (1.6x slower) | 3.69ms (**20.4x faster**) | |
36 | | -| **Medium JSON** (2.6KB) | 73.87ms | 57.98ms (**1.3x faster**) | 125.73ms (1.7x slower) | 4.32ms (**17.1x faster**) | |
37 | | -| **Large JSON** (323KB) | 419.67ms | 328.98ms (**1.3x faster**) | 517.51ms (1.2x slower) | 67.13ms (**6.3x faster**) | |
38 | | -| **Very Large JSON** (1.6MB) | 2.09s | 1.86s (**1.1x faster**) | 1.42s (**1.5x faster**) | 287.58ms (**7.3x faster**) | |
| 34 | +| Test Case | Python | Rust | Go | Zig | |
| 35 | +|-----------|--------|------|-----|-----| |
| 36 | +| Small (47B) | 40.12µs | 1.45µs | 4.65ms | 3.74ms | |
| 37 | +| Medium (3.2KB) | 2.14ms | 71.28µs | 4.07ms | 3.28ms | |
| 38 | +| bigexample (2KB) | 819.46µs | 32.88µs | 4.02ms | 2.96ms | |
| 39 | +| Large (32KB) | 21.08ms | 739.89µs | 4.05ms | 6.11ms | |
| 40 | +| Very Large (323KB) | 212.61ms | 7.55ms | 4.38ms | 33.24ms | |
39 | 41 |
|
40 | | -### Summary (Average Across All Tests) |
| 42 | +### Speedup vs Pure Python |
41 | 43 |
|
42 | | -| Implementation | Avg Time | vs CPython 3.14.2 | |
43 | | -|----------------|----------|-------------------| |
44 | | -| **Go** | 90.68ms | **7.34x faster** 🚀 | |
45 | | -| **PyPy 3.10.16** | 545.58ms | **1.22x faster** | |
46 | | -| **CPython 3.15.0a4** | 575.45ms | **1.16x faster** | |
47 | | -| **CPython 3.14.2** | 665.23ms | baseline | |
| 44 | +| Test Case | Rust | Go | Zig | |
| 45 | +|-----------|------|-----|-----| |
| 46 | +| Small (47B) | **27.6x** | 0.0x* | 0.0x* | |
| 47 | +| Medium (3.2KB) | **30.0x** | 0.5x* | 0.7x* | |
| 48 | +| bigexample (2KB) | **24.9x** | 0.2x* | 0.3x* | |
| 49 | +| Large (32KB) | **28.5x** | 5.2x | 3.5x | |
| 50 | +| Very Large (323KB) | **28.2x** | **48.5x** | 6.4x | |
| 51 | + |
| 52 | +*CLI tools have process spawn overhead (~3-4ms) which dominates for small inputs |
48 | 53 |
|
49 | 54 | ## Key Observations |
50 | 55 |
|
51 | | -### 1. Go is the Clear Winner |
| 56 | +### 1. Rust Extension is the Best Choice for Python Users 🦀 |
52 | 57 |
|
53 | | -Go outperforms all Python implementations by a significant margin: |
54 | | -- **7.34x faster** than CPython 3.14.2 on average |
55 | | -- Up to **20x faster** for small inputs due to minimal startup overhead |
56 | | -- Consistent performance across all input sizes |
| 58 | +The Rust extension (json2xml-rs) provides: |
| 59 | +- **~28x faster** than pure Python consistently across all input sizes |
| 60 | +- **Zero process overhead** - called directly from Python |
| 61 | +- **Automatic fallback** - pure Python used if Rust unavailable |
| 62 | +- **Easy install**: `pip install json2xml[fast]` |
57 | 63 |
|
58 | | -### 2. CPython 3.15.0a4 Shows Promising Improvements |
| 64 | +### 2. Go Excels for Large CLI Workloads 🚀 |
59 | 65 |
|
60 | | -The latest Python alpha demonstrates consistent performance gains: |
61 | | -- **13-35% faster** than CPython 3.14.2 across all test sizes |
62 | | -- Improvements likely due to ongoing interpreter optimizations |
| 66 | +For very large inputs (323KB+): |
| 67 | +- **48.5x faster** than Python |
| 68 | +- But ~3-4ms startup overhead hurts small file performance |
| 69 | +- Best for batch processing or large file conversions |
63 | 70 |
|
64 | | -### 3. PyPy Has Interesting Trade-offs |
| 71 | +### 3. Zig is Competitive but Has Trade-offs |
65 | 72 |
|
66 | | -PyPy's JIT compiler creates a unique performance profile: |
67 | | -- **Slower for small/medium inputs**: JIT compilation overhead hurts for quick operations |
68 | | -- **Faster for very large inputs**: JIT shines on the 5K record test (1.5x faster than CPython) |
69 | | -- Best suited for long-running processes or batch processing |
| 73 | +- Consistent ~3ms startup overhead |
| 74 | +- Good for medium-large files (3-6x faster than Python) |
| 75 | +- Less optimized than Go for very large inputs |
70 | 76 |
|
71 | | -### 4. Startup Overhead Dominates Small Inputs |
| 77 | +### 4. Process Spawn Overhead Matters |
72 | 78 |
|
73 | | -Python's interpreter startup time is significant: |
74 | | -- CPython takes **55-75ms** even for 47 bytes of JSON |
75 | | -- Go takes only **3.7ms** for the same operation |
76 | | -- For CLI tools processing small files, Go provides a much better user experience |
| 79 | +CLI tools (Go, Zig) have ~3-4ms process spawn overhead: |
| 80 | +- Dominates for small inputs (makes them appear slower than Python!) |
| 81 | +- Negligible for large inputs where actual work dominates |
| 82 | +- Rust extension avoids this entirely by being a native Python module |
77 | 83 |
|
78 | 84 | ## When to Use Each Implementation |
79 | 85 |
|
80 | | -| Use Case | Recommended | |
81 | | -|----------|-------------| |
82 | | -| CLI tool for small/medium files | **Go** (json2xml-go) | |
83 | | -| High-throughput batch processing | **Go** or **PyPy** | |
84 | | -| Integration with Python codebase | **CPython 3.15+** | |
85 | | -| One-off conversions in scripts | **CPython** (any version) | |
86 | | - |
87 | | -## Running the Benchmarks |
| 86 | +| Use Case | Recommended | Why | |
| 87 | +|----------|-------------|-----| |
| 88 | +| Python library calls | **Rust** (`pip install json2xml[fast]`) | 28x faster, no overhead | |
| 89 | +| Small files via CLI | **Rust** via Python | CLI overhead dominates | |
| 90 | +| Large files via CLI | **Go** (json2xml-go) | 48x faster for 300KB+ | |
| 91 | +| Batch processing | **Go** or **Rust** | Both excellent | |
| 92 | +| Pure Python required | **Python** (json2xml) | Always available | |
88 | 93 |
|
89 | | -### Python Multi-Implementation Benchmark |
| 94 | +## Installation |
90 | 95 |
|
91 | 96 | ```bash |
92 | | -# Set the Go CLI path |
93 | | -export JSON2XML_GO_CLI=/path/to/json2xml-go |
| 97 | +# Pure Python (always works) |
| 98 | +pip install json2xml |
94 | 99 |
|
95 | | -# Run the benchmark |
96 | | -python benchmark_multi_python.py |
| 100 | +# With Rust acceleration (recommended) |
| 101 | +pip install json2xml[fast] |
| 102 | + |
| 103 | +# Go CLI |
| 104 | +go install github.com/vinitkumar/json2xml-go@latest |
| 105 | + |
| 106 | +# Zig CLI |
| 107 | +# See: github.com/nicholasgriffintn/json2xml-zig |
97 | 108 | ``` |
98 | 109 |
|
99 | | -### Simple Python vs Go Benchmark |
| 110 | +## Running the Benchmarks |
| 111 | + |
| 112 | +### Comprehensive Benchmark (All Implementations) |
100 | 113 |
|
101 | 114 | ```bash |
102 | | -# Set paths via environment variables (optional) |
103 | | -export JSON2XML_GO_CLI=/path/to/json2xml-go |
104 | | -export JSON2XML_EXAMPLES_DIR=/path/to/examples |
| 115 | +python benchmark_all.py |
| 116 | +``` |
105 | 117 |
|
106 | | -# Run the benchmark |
107 | | -python benchmark.py |
| 118 | +### Rust vs Python Only |
| 119 | + |
| 120 | +```bash |
| 121 | +python benchmark_rust.py |
108 | 122 | ``` |
109 | 123 |
|
110 | | -## Reproducing Results |
| 124 | +### Multi-Python Version Benchmark |
111 | 125 |
|
112 | | -1. Install required Python versions using `uv`: |
113 | | - ```bash |
114 | | - uv python install 3.14 3.15.0a4 [email protected] |
115 | | - ``` |
| 126 | +```bash |
| 127 | +python benchmark_multi_python.py |
| 128 | +``` |
116 | 129 |
|
117 | | -2. Build the Go binary: |
118 | | - ```bash |
119 | | - cd /path/to/json2xml-go |
120 | | - go build -o json2xml-go ./cmd/json2xml-go |
121 | | - ``` |
| 130 | +## Related Projects |
122 | 131 |
|
123 | | -3. Run the multi-Python benchmark: |
124 | | - ```bash |
125 | | - cd /path/to/json2xml |
126 | | - python benchmark_multi_python.py |
127 | | - ``` |
| 132 | +- **Go version**: [github.com/vinitkumar/json2xml-go](https://github.com/vinitkumar/json2xml-go) |
| 133 | +- **Zig version**: [github.com/nicholasgriffintn/json2xml-zig](https://github.com/nicholasgriffintn/json2xml-zig) |
0 commit comments