Skip to content

Commit 3757fa0

Browse files
committed
perf: streamline manual line streaming
Normalize public layoutNextLine() and layoutNextLineRange() starts once, keep the chunk index, and step with that known chunk instead of rediscovering it. Refresh Chrome and Safari benchmark snapshots plus the status dashboard. Refs #140.
1 parent 1d17369 commit 3757fa0

7 files changed

Lines changed: 263 additions & 286 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- Numeric CSS-pixel `letterSpacing` support on `prepare()`, `prepareWithSegments()`, and each existing rich-inline item (#108, #156).
88

9+
### Changed
10+
11+
- `layoutNextLine()` and `layoutNextLineRange()` now avoid redundant chunk lookup in chunk-heavy manual layout paths (#140).
12+
913
### Fixed
1014

1115
- CJK text followed by opening bracket annotations now wraps like browsers instead of leaving the opening bracket on the previous line (#148).

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Current priorities:
1515
- If we add another Southeast Asian canary, prefer a clean source text that broadens the class instead of another wrapped/legal/raw-source artifact.
1616
- Expand the sampled font matrix only where a canary still looks genuinely imperfect.
1717
- Treat strongly font-sensitive or shaping-sensitive misses as boundary-finding for the current architecture, not automatic invitations for another local glue rule.
18-
- Keep the hot `layout()` path simple and allocation-light while the rich path absorbs more userland layout needs.
18+
- Keep the height-only `layout()` path simple and allocation-light, and use the rich/manual benchmarks to steer range/cursor layout work.
1919
- If chunk-heavy manual layout keeps growing, consider a stateful streaming variant or a cursor-carried chunk hint so sequential `layoutNextLine()` flows can stay overall linear instead of paying a lookup per emitted line.
2020
- If arbitrary interior rich cursors become common, consider a compact `segmentIndex -> chunkIndex` side table, ideally only on rich prepared handles or only when `chunks.length > 1`.
2121

benchmarks/chrome.json

Lines changed: 66 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
"results": [
44
{
55
"label": "Our library: prepare()",
6-
"ms": 18.800000071525574,
6+
"ms": 18.100000023841858,
77
"desc": "One cold 500-text measurement batch"
88
},
99
{
1010
"label": "Our library: layout()",
11-
"ms": 0.14825000047683717,
11+
"ms": 0.14450000047683714,
1212
"desc": "Normalized hot-path throughput per 500-text batch"
1313
},
1414
{
1515
"label": "DOM batch",
16-
"ms": 3.899999976158142,
16+
"ms": 3.850000023841858,
1717
"desc": "Single 400→300px batch resize: write all, then read all"
1818
},
1919
{
2020
"label": "DOM interleaved",
21-
"ms": 44.75,
21+
"ms": 43.5,
2222
"desc": "Single 400→300px batch resize: write + read per div"
2323
}
2424
],
@@ -30,24 +30,24 @@
3030
},
3131
{
3232
"label": "Our library: layoutWithLines()",
33-
"ms": 0.05250000357627869,
33+
"ms": 0.053749996423721316,
3434
"desc": "60-text shared-corpus batch across widths 180/220/260px; materializes text lines"
3535
},
3636
{
3737
"label": "Our library: walkLineRanges()",
38-
"ms": 0.023750001192092897,
38+
"ms": 0.025,
3939
"desc": "60-text shared-corpus batch across widths 180/220/260px; line ranges only, no line text strings"
4040
},
4141
{
4242
"label": "Our library: layoutNextLine()",
43-
"ms": 0.04500000178813934,
43+
"ms": 0.0449999988079071,
4444
"desc": "60-text shared-corpus batch across widths 180/220/260px; streaming line-by-line layout"
4545
}
4646
],
4747
"richInlineResults": [
4848
{
4949
"label": "Our library: measureRichInlineStats()",
50-
"ms": 0.010000002384185792,
50+
"ms": 0.011250001192092896,
5151
"desc": "36 rich-text inline flow shared-corpus texts across widths 180/220/260px; stats only"
5252
},
5353
{
@@ -57,56 +57,56 @@
5757
},
5858
{
5959
"label": "Our library: materializeRichInlineLineRange()",
60-
"ms": 0.04250000119209289,
60+
"ms": 0.0449999988079071,
6161
"desc": "36 rich-text inline flow shared-corpus texts across widths 180/220/260px; range walker plus per-line materialization"
6262
},
6363
{
6464
"label": "Our library: layoutNextRichInlineLineRange() + materializeRichInlineLineRange()",
65-
"ms": 0.04375,
65+
"ms": 0.04250000119209289,
6666
"desc": "36 rich-text inline flow shared-corpus texts across widths 180/220/260px; streaming range walk plus per-line materialization"
6767
}
6868
],
6969
"richPreWrapResults": [
7070
{
7171
"label": "Our library: measureLineStats()",
72-
"ms": 0.26999999880790715,
72+
"ms": 0.3049999952316284,
7373
"desc": "12 generated pre-wrap texts with 320 hard-break chunks across widths 220/260/320px; stats only"
7474
},
7575
{
7676
"label": "Our library: layoutWithLines()",
77-
"ms": 0.4299999952316284,
77+
"ms": 0.42000000476837157,
7878
"desc": "12 generated pre-wrap texts with 320 hard-break chunks across widths 220/260/320px; materializes text lines"
7979
},
8080
{
8181
"label": "Our library: walkLineRanges()",
82-
"ms": 0.23500000238418578,
82+
"ms": 0.24499999284744262,
8383
"desc": "12 generated pre-wrap texts with 320 hard-break chunks across widths 220/260/320px; line ranges only, no line text strings"
8484
},
8585
{
8686
"label": "Our library: layoutNextLine()",
87-
"ms": 1.1225000023841858,
87+
"ms": 0.9475000023841857,
8888
"desc": "12 generated pre-wrap texts with 320 hard-break chunks across widths 220/260/320px; streaming line-by-line layout"
8989
}
9090
],
9191
"richLongResults": [
9292
{
9393
"label": "Our library: measureLineStats()",
94-
"ms": 1.6650000005960464,
94+
"ms": 1.6537499994039535,
9595
"desc": "8 Arabic long-form texts across widths 240/300/360px; stats only"
9696
},
9797
{
9898
"label": "Our library: layoutWithLines()",
99-
"ms": 5.660000002384185,
99+
"ms": 5.550000000000001,
100100
"desc": "8 Arabic long-form texts across widths 240/300/360px; materializes text lines"
101101
},
102102
{
103103
"label": "Our library: walkLineRanges()",
104-
"ms": 2.221249997615814,
104+
"ms": 2.208750000596046,
105105
"desc": "8 Arabic long-form texts across widths 240/300/360px; line ranges only, no line text strings"
106106
},
107107
{
108108
"label": "Our library: layoutNextLine()",
109-
"ms": 5.613749998807907,
109+
"ms": 5.165000000596047,
110110
"desc": "8 Arabic long-form texts across widths 240/300/360px; streaming line-by-line layout"
111111
}
112112
],
@@ -122,7 +122,7 @@
122122
"width": 300,
123123
"lineCount": 193,
124124
"analysisMs": 2.3999998569488525,
125-
"measureMs": 4.299999713897705,
125+
"measureMs": 4.1000001430511475,
126126
"prepareMs": 6.599999904632568,
127127
"layoutMs": 0.02600000023841858
128128
},
@@ -136,10 +136,10 @@
136136
"breakableSegments": 1,
137137
"width": 300,
138138
"lineCount": 380,
139-
"analysisMs": 4.8999998569488525,
140-
"measureMs": 8.299999952316284,
141-
"prepareMs": 13.400000095367432,
142-
"layoutMs": 0.049499999284744266
139+
"analysisMs": 4.700000047683716,
140+
"measureMs": 7.900000333786011,
141+
"prepareMs": 12.700000047683716,
142+
"layoutMs": 0.04899999976158142
143143
},
144144
{
145145
"id": "ko-unsu-joh-eun-nal",
@@ -151,10 +151,10 @@
151151
"breakableSegments": 0,
152152
"width": 300,
153153
"lineCount": 428,
154-
"analysisMs": 3.4000000953674316,
155-
"measureMs": 9.399999856948853,
156-
"prepareMs": 12.700000047683716,
157-
"layoutMs": 0.07899999976158142
154+
"analysisMs": 3.3999998569488525,
155+
"measureMs": 8.500000238418579,
156+
"prepareMs": 11.900000095367432,
157+
"layoutMs": 0.0775
158158
},
159159
{
160160
"id": "ko-sonagi",
@@ -166,10 +166,10 @@
166166
"breakableSegments": 2,
167167
"width": 300,
168168
"lineCount": 332,
169-
"analysisMs": 2.5,
170-
"measureMs": 7.199999809265137,
171-
"prepareMs": 9.799999952316284,
172-
"layoutMs": 0.05899999976158142
169+
"analysisMs": 2.4000000953674316,
170+
"measureMs": 6.3999998569488525,
171+
"prepareMs": 8.899999856948853,
172+
"layoutMs": 0.05800000071525574
173173
},
174174
{
175175
"id": "zh-zhufu",
@@ -181,9 +181,9 @@
181181
"breakableSegments": 4,
182182
"width": 300,
183183
"lineCount": 626,
184-
"analysisMs": 7.700000047683716,
185-
"measureMs": 14.699999809265137,
186-
"prepareMs": 21.59999990463257,
184+
"analysisMs": 7.200000047683716,
185+
"measureMs": 13.799999952316284,
186+
"prepareMs": 20.799999952316284,
187187
"layoutMs": 0.08
188188
},
189189
{
@@ -196,10 +196,10 @@
196196
"breakableSegments": 14,
197197
"width": 300,
198198
"lineCount": 375,
199-
"analysisMs": 4.700000047683716,
200-
"measureMs": 8.399999856948853,
201-
"prepareMs": 13.399999856948853,
202-
"layoutMs": 0.0475
199+
"analysisMs": 4.299999952316284,
200+
"measureMs": 7.3999998569488525,
201+
"prepareMs": 11.799999952316284,
202+
"layoutMs": 0.04700000047683716
203203
},
204204
{
205205
"id": "th-nithan-vetal-story-1",
@@ -211,10 +211,10 @@
211211
"breakableSegments": 8087,
212212
"width": 300,
213213
"lineCount": 1024,
214-
"analysisMs": 10.299999952316284,
215-
"measureMs": 9.599999904632568,
216-
"prepareMs": 19.59999990463257,
217-
"layoutMs": 0.08649999976158142
214+
"analysisMs": 9.800000190734863,
215+
"measureMs": 7.099999666213989,
216+
"prepareMs": 17.5,
217+
"layoutMs": 0.08700000047683716
218218
},
219219
{
220220
"id": "my-cunning-heron-teacher",
@@ -226,10 +226,10 @@
226226
"breakableSegments": 422,
227227
"width": 300,
228228
"lineCount": 81,
229-
"analysisMs": 0.7999999523162842,
230-
"measureMs": 0.8000001907348633,
231-
"prepareMs": 1.6000001430511475,
232-
"layoutMs": 0.0070000004768371584
229+
"analysisMs": 0.7000000476837158,
230+
"measureMs": 0.7999999523162842,
231+
"prepareMs": 1.5999999046325684,
232+
"layoutMs": 0.006999999284744263
233233
},
234234
{
235235
"id": "my-bad-deeds-return-to-you-teacher",
@@ -244,7 +244,7 @@
244244
"analysisMs": 0.5,
245245
"measureMs": 0.5999999046325684,
246246
"prepareMs": 1.0999999046325684,
247-
"layoutMs": 0.004499999284744263
247+
"layoutMs": 0.004500000476837158
248248
},
249249
{
250250
"id": "ur-chughd",
@@ -257,9 +257,9 @@
257257
"width": 300,
258258
"lineCount": 351,
259259
"analysisMs": 3.6000001430511475,
260-
"measureMs": 3.8999998569488525,
261-
"prepareMs": 8,
262-
"layoutMs": 0.04299999952316284
260+
"measureMs": 3.6999998092651367,
261+
"prepareMs": 7.900000095367432,
262+
"layoutMs": 0.0425
263263
},
264264
{
265265
"id": "km-prachum-reuang-preng-khmer-volume-7-stories-1-10",
@@ -271,10 +271,10 @@
271271
"breakableSegments": 4010,
272272
"width": 300,
273273
"lineCount": 591,
274-
"analysisMs": 8.700000047683716,
275-
"measureMs": 5.099999904632568,
276-
"prepareMs": 13.799999952316284,
277-
"layoutMs": 0.085
274+
"analysisMs": 7.700000047683716,
275+
"measureMs": 4.8999998569488525,
276+
"prepareMs": 13.5,
277+
"layoutMs": 0.08399999976158141
278278
},
279279
{
280280
"id": "hi-eidgah",
@@ -286,10 +286,10 @@
286286
"breakableSegments": 4089,
287287
"width": 300,
288288
"lineCount": 653,
289-
"analysisMs": 6.1000001430511475,
290-
"measureMs": 8.399999856948853,
291-
"prepareMs": 14.699999809265137,
292-
"layoutMs": 0.06950000047683716
289+
"analysisMs": 6,
290+
"measureMs": 7.599999904632568,
291+
"prepareMs": 14.299999952316284,
292+
"layoutMs": 0.06900000095367431
293293
},
294294
{
295295
"id": "synthetic-long-breakable-runs",
@@ -301,10 +301,10 @@
301301
"breakableSegments": 1540,
302302
"width": 300,
303303
"lineCount": 2860,
304-
"analysisMs": 8.800000190734863,
305-
"measureMs": 13,
306-
"prepareMs": 21.5,
307-
"layoutMs": 0.3125
304+
"analysisMs": 8.600000143051147,
305+
"measureMs": 11.299999952316284,
306+
"prepareMs": 20.5,
307+
"layoutMs": 0.30949999928474425
308308
},
309309
{
310310
"id": "ar-risalat-al-ghufran-part-1",
@@ -316,10 +316,10 @@
316316
"breakableSegments": 18745,
317317
"width": 300,
318318
"lineCount": 2643,
319-
"analysisMs": 28.200000047683716,
320-
"measureMs": 47.19999980926514,
321-
"prepareMs": 75.90000009536743,
322-
"layoutMs": 0.2739999997615814
319+
"analysisMs": 26.399999856948853,
320+
"measureMs": 43.90000009536743,
321+
"prepareMs": 70.59999990463257,
322+
"layoutMs": 0.2714999997615814
323323
}
324324
]
325325
}

0 commit comments

Comments
 (0)