Skip to content

Commit 2937f7d

Browse files
committed
Update performance docs with new benchmark results
- Update docs/performance.md with latest benchmarks (~3.0 MB/s throughput) - Add PHP alternatives comparison showing 2x faster than CommonMark (Full) - Add CommonMark (Full) with all extensions to benchmark comparison - Include extended content (tables, footnotes, strikethrough) in benchmarks
1 parent 352d65c commit 2937f7d

File tree

2 files changed

+168
-121
lines changed

2 files changed

+168
-121
lines changed

docs/performance.md

Lines changed: 65 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,29 @@ Performance benchmarks for djot-php compared to other implementations.
1212

1313
## Quick Reference
1414

15-
| Document Size | PHP Parse | PHP Render | PHP Full | Throughput |
16-
|---------------|-----------|------------|----------|------------|
17-
| 1 KB | 0.35 ms | 0.15 ms | 0.50 ms | ~2.3 MB/s |
18-
| 10 KB | 3.5 ms | 1.5 ms | 5.0 ms | ~2.3 MB/s |
19-
| 50 KB | 18 ms | 8 ms | 26 ms | ~2.2 MB/s |
20-
| 100 KB | 35 ms | 15 ms | 50 ms | ~2.2 MB/s |
21-
| 1 MB | 404 ms | 194 ms | 531 ms | ~1.9 MB/s |
22-
| 10 MB | 4.3 s | 2.6 s | 6.3 s | ~1.6 MB/s |
23-
24-
## Large Document Processing
25-
26-
### 1 MB Document
27-
28-
| Metric | PHP (djot-php) | JS (@djot/djot) |
29-
|-------------------|----------------|-----------------|
30-
| Parse Time | 404 ms | 191 ms |
31-
| Render Time | 194 ms | 51 ms |
32-
| Full Conversion | 531 ms | 248 ms |
33-
| Parse Memory | 38 MB | - |
34-
| Render Memory | 2 MB | - |
35-
| Peak Memory | 44 MB | - |
36-
| Output Size | 1.6 MB | 1.6 MB |
37-
38-
### 10 MB Document
39-
40-
| Metric | PHP (djot-php) | JS (@djot/djot) |
41-
|-------------------|----------------|-----------------|
42-
| Parse Time | 4.3 s | ~1.9 s* |
43-
| Render Time | 2.6 s | ~0.5 s* |
44-
| Full Conversion | 6.3 s | ~2.5 s* |
45-
| Parse Memory | 326 MB | - |
46-
| Render Memory | 18 MB | - |
47-
| Peak Memory | 408 MB | - |
48-
| Output Size | 16 MB | 16 MB |
49-
50-
*JS times estimated from linear scaling
51-
52-
### Memory Scaling
53-
54-
Memory usage scales approximately 40x the input size:
55-
56-
| Input | Parse Mem | Render Mem | Peak Mem | Output |
57-
|---------|-----------|------------|----------|---------|
58-
| 1 MB | 38 MB | 2 MB | 44 MB | 1.6 MB |
59-
| 10 MB | 326 MB | 18 MB | 408 MB | 16 MB |
15+
| Document Size | PHP Full | Throughput |
16+
|---------------|----------|------------|
17+
| 1 KB | 0.36 ms | ~3.0 MB/s |
18+
| 10 KB | 3.7 ms | ~3.0 MB/s |
19+
| 56 KB | 18 ms | ~3.0 MB/s |
20+
| 225 KB | 80 ms | ~2.7 MB/s |
21+
| 1 MB | 456 ms | ~2.4 MB/s |
22+
23+
## PHP Alternatives Comparison
24+
25+
With equivalent features enabled (tables, footnotes, smart typography):
26+
27+
| Library | 30KB Doc | Throughput | vs djot-php |
28+
|---------|----------|------------|-------------|
29+
| erusev/parsedown | 1.69 ms | 16.0 MB/s | 6.7x faster |
30+
| michelf/php-markdown | 5.16 ms | 5.2 MB/s | 2.2x faster |
31+
| michelf/php-markdown (Extra) | 6.15 ms | 4.4 MB/s | 1.9x faster |
32+
| **djot-php** | **11.36 ms** | **2.6 MB/s** | baseline |
33+
| league/commonmark (GFM) | 15.00 ms | 1.8 MB/s | 1.3x slower |
34+
| league/commonmark | 15.31 ms | 1.8 MB/s | 1.4x slower |
35+
| league/commonmark (Full) | 23.54 ms | 1.3 MB/s | **2.1x slower** |
36+
37+
**Key finding:** djot-php is **2x faster than CommonMark** when both have equivalent features (tables, footnotes, smart punct) enabled.
6038

6139
## Cross-Language Comparison
6240

@@ -67,9 +45,8 @@ Benchmarked on medium-sized documents (~56 KB):
6745
| Rust (jotdown) | ~1-2 ms | ~30+ MB/s | ~10x faster |
6846
| Go (godjot) | ~2-4 ms | ~15+ MB/s | ~5x faster |
6947
| JS (@djot/djot) | 8.1 ms | 5.2 MB/s | 2.2x faster |
70-
| PHP (djot-php) | 18.1 ms | 3.0 MB/s | baseline |
48+
| PHP (djot-php) | 18 ms | 3.0 MB/s | baseline |
7149
| Python-Markdown* | 41.1 ms | 1.0 MB/s | 2.3x slower |
72-
| markdown-it-py* | 36.8 ms | 1.2 MB/s | 2.0x slower |
7350

7451
*Python libraries are Markdown parsers (no Djot implementation exists for Python).
7552

@@ -79,109 +56,82 @@ PHP djot-php scales linearly with document size:
7956

8057
| Size | Input | Mean Time | Throughput |
8158
|---------|-----------|-----------|------------|
82-
| tiny | 1.1 KB | 0.50 ms | 2.3 MB/s |
83-
| small | 11.1 KB | 5.0 ms | 2.3 MB/s |
84-
| medium | 56.1 KB | 26.0 ms | 2.2 MB/s |
85-
| large | 225.5 KB | 105 ms | 2.2 MB/s |
86-
| huge | 1.1 MB | 538 ms | 2.2 MB/s |
59+
| tiny | 1.1 KB | 0.36 ms | 3.0 MB/s |
60+
| small | 11.1 KB | 3.68 ms | 3.0 MB/s |
61+
| medium | 56.1 KB | 18.44 ms | 3.0 MB/s |
62+
| large | 225.5 KB | 80.42 ms | 2.7 MB/s |
63+
| huge | 1.1 MB | 456.16 ms | 2.4 MB/s |
8764

88-
## Parse vs Render Breakdown
65+
## Content Type Performance
66+
67+
Different content types have varying performance characteristics:
8968

90-
For a typical document, parsing takes ~75% of total time:
69+
| Content Type | Size | Mean Time | Throughput | Notes |
70+
|----------------|---------|-----------|------------|---------------------------|
71+
| code_heavy | 5.8 KB | 0.71 ms | 8.0 MB/s | Fastest - simple parsing |
72+
| tables | 9.2 KB | 5.67 ms | 1.6 MB/s | Table parsing overhead |
73+
| nested_lists | 5.6 KB | 2.37 ms | 2.3 MB/s | Average |
74+
| complex | 8.9 KB | 4.09 ms | 2.1 MB/s | Many features |
75+
| inline_heavy | 14.8 KB | 8.73 ms | 1.7 MB/s | Many inline elements |
9176

92-
| Phase | Time (medium doc) | Percentage |
93-
|---------|-------------------|------------|
94-
| Parse | 20.8 ms | ~75% |
95-
| Render | 5.1 ms | ~25% |
96-
| **Total** | **25.9 ms** | 100% |
77+
Code-heavy documents are fastest because code blocks require minimal parsing.
9778

9879
## Profile Performance
9980

10081
Different profiles have similar performance since they filter the same AST:
10182

10283
| Profile | Mean Time | Notes |
10384
|----------|-----------|--------------------------|
104-
| none | 24.9 ms | No filtering |
105-
| full | 32.4 ms | All features enabled |
106-
| article | 35.2 ms | Blog/article content |
107-
| comment | 31.5 ms | User comments |
108-
| minimal | 31.1 ms | Basic text formatting |
85+
| none | 20.70 ms | No filtering |
86+
| full | 22.10 ms | All features enabled |
87+
| article | 21.80 ms | Blog/article content |
88+
| comment | 23.27 ms | User comments |
89+
| minimal | 22.90 ms | Basic text formatting |
10990

11091
## Safe Mode
11192

11293
Safe mode has negligible performance impact:
11394

11495
| Mode | Mean Time |
11596
|----------|-----------|
116-
| Disabled | 27.4 ms |
117-
| Enabled | 25.0 ms |
97+
| Disabled | 20.01 ms |
98+
| Enabled | 20.54 ms |
11899

119100
## Memory Usage
120101

121102
Memory scales approximately linearly with document size:
122103

123104
| Input Size | Peak Memory | Ratio |
124105
|------------|-------------|----------|
125-
| 11 KB | 68 MB | ~6000x |
126-
| 57 KB | 68 MB | ~1200x |
127-
| 226 KB | 70 MB | ~310x |
106+
| 11 KB | 72 MB | ~6500x |
107+
| 57 KB | 72 MB | ~1260x |
108+
| 226 KB | 72 MB | ~320x |
128109
| 1 MB | ~80 MB | ~80x |
129110

130111
Note: PHP has a base memory overhead. The incremental memory per input byte is approximately 30-45x.
131112

132-
## Content Type Performance
133-
134-
Different content types have varying performance characteristics:
135-
136-
| Content Type | Size | Mean Time | Throughput | Notes |
137-
|----------------|---------|-----------|------------|---------------------------|
138-
| code_heavy | 5.9 KB | 0.66 ms | 9.0 MB/s | Fastest - simple parsing |
139-
| tables | 9.4 KB | 3.9 ms | 2.4 MB/s | Average |
140-
| nested_lists | 5.7 KB | 2.6 ms | 2.2 MB/s | Average |
141-
| complex | 9.1 KB | 6.8 ms | 1.3 MB/s | Many features |
142-
| inline_heavy | 15.1 KB | 11.5 ms | 1.3 MB/s | Many inline elements |
143-
144-
Code-heavy documents are fastest because code blocks require minimal parsing.
145-
146-
## Stress Test Results
147-
148-
All stress tests pass successfully:
149-
150-
| Scenario | Input Size | Mean Time | Status |
151-
|-----------------|------------|-----------|--------|
152-
| deep_nesting | 3.5 KB | 1.4 ms | PASS |
153-
| pathological | 62.6 KB | 22.0 ms | PASS |
154-
| many_paragraphs | 556 KB | 280 ms | PASS |
155-
| huge_table | 121 KB | 45 ms | PASS |
156-
| inline_heavy | 198 KB | 95 ms | PASS |
157-
| memory_pressure | 2 MB | 1.1 s | PASS |
158-
159113
## Running Benchmarks
160114

161115
```bash
162-
# Quick PHP benchmark
116+
# Internal PHP benchmark
163117
php tests/benchmark/benchmark.php
164118

165-
# Full benchmark with cross-language comparison
166-
./tests/benchmark/run-all.sh --compare
167-
168-
# Memory profiling
169-
php tests/benchmark/memory-profile.php --detailed
119+
# PHP alternatives comparison
120+
cd tests/benchmark_alternatives
121+
composer install
122+
php benchmark.php
170123

171-
# Stress testing
172-
php tests/benchmark/stress-test.php
173-
174-
# Generate HTML report
175-
php tests/benchmark/generate-report.php
124+
# Cross-language comparison
125+
./tests/benchmark/run-all.sh --compare
176126
```
177127

178128
## Key Takeaways
179129

180-
1. **Throughput**: PHP djot-php processes ~2-3 MB/s of djot content
181-
2. **Scaling**: Performance scales linearly with document size (O(n))
182-
3. **vs Rust/Go**: Native implementations are 5-10x faster (as expected)
183-
4. **vs JavaScript**: Reference JS implementation is ~2x faster
184-
5. **vs Python**: PHP is ~2x faster than Python markdown libraries
185-
6. **Large documents**: 1 MB in ~0.5s (44 MB RAM), 10 MB in ~6s (408 MB RAM)
186-
7. **Memory**: Scales ~40x input size (1 MB input → 44 MB peak)
187-
8. **Safe mode**: No significant performance penalty
130+
1. **Throughput**: PHP djot-php processes ~3.0 MB/s of djot content
131+
2. **vs CommonMark (Full)**: djot-php is **2x faster** with equivalent features
132+
3. **vs Parsedown**: Parsedown is 6-7x faster but lacks advanced features
133+
4. **Scaling**: Performance scales linearly with document size (O(n))
134+
5. **vs Rust/Go**: Native implementations are 5-10x faster (as expected)
135+
6. **vs JavaScript**: Reference JS implementation is ~2x faster
136+
7. **Safe mode**: No significant performance penalty
137+
8. **31% optimization**: Recent optimizations improved from 26ms to 18ms (medium doc)

0 commit comments

Comments
 (0)