@@ -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
10081Different 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
11293Safe 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
121102Memory 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
130111Note: 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
163117php 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