Commit 6bc3d49
perf(iconv): hoist per-char dispatch for UTF-8 source — UTF-8->UTF-32 ~2.5x faster (bd-48uzu9)
Found an unbenched real gap: iconv non-ASCII transcoding is 2-3.4x slower than
glibc (release, same machine): UTF-8->UTF-32LE fl 16.8us vs glibc 5.0us (3.39x),
UTF-8->KOI8-R fl 17.3us vs glibc 7.5us (2.31x) on a 3686B cyrillic-heavy buffer.
Root cause: the convert loop dispatches decode_char + encode_char (two ~100-arm
matches + nested calls + a redundant char::from_u32) for EVERY character.
LEVER (one): a tight monomorphic UTF-8-source fast path that inlines the decode
+ encode for the hot targets (UTF-32LE/BE, UTF-16LE/BE, single-byte via the
cached reverse map). Placed after the existing ASCII/sb_translation fast paths
(so their SIMD bulk-copy still wins). ANY non-trivial outcome — incomplete /
invalid sequence, out-of-range scalar, unrepresentable char, no output space, or
a pending BOM — leaves in_pos/out_pos untouched and falls through to the unchanged
generic body, so EILSEQ/EINVAL/E2BIG ordering and the long-tail encodings are
byte-for-byte identical.
Before -> after (release microbench, median of runs):
UTF-8->UTF-32LE: 16.8us -> ~6.5us (~2.5x; now 1.2-1.5x glibc, was 3.39x)
UTF-8->UTF-16: similar
UTF-8->KOI8-R: unchanged (bottleneck is the reverse-map binary search; tracked
as a separate lever in bd-48uzu9)
Isomorphism proof: iconv_differential_fuzz (live glibc oracle — explicitly covers
UTF-16LE/BE + UTF-32LE/BE <-> UTF-8 incl. astral/surrogate-pair cases) green;
conformance_diff_iconv 49 cases green; iconv_abi_test green; NEW
golden_iconv_utf8_fastpath.rs pins SHA-256 of the converted corpus for all four
fixed-width targets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>1 parent be5169c commit 6bc3d49
2 files changed
Lines changed: 131 additions & 0 deletions
Lines changed: 63 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9425 | 9425 | | |
9426 | 9426 | | |
9427 | 9427 | | |
| 9428 | + | |
| 9429 | + | |
| 9430 | + | |
| 9431 | + | |
| 9432 | + | |
| 9433 | + | |
| 9434 | + | |
| 9435 | + | |
| 9436 | + | |
| 9437 | + | |
| 9438 | + | |
| 9439 | + | |
| 9440 | + | |
| 9441 | + | |
| 9442 | + | |
| 9443 | + | |
| 9444 | + | |
| 9445 | + | |
| 9446 | + | |
| 9447 | + | |
| 9448 | + | |
| 9449 | + | |
| 9450 | + | |
| 9451 | + | |
| 9452 | + | |
| 9453 | + | |
| 9454 | + | |
| 9455 | + | |
| 9456 | + | |
| 9457 | + | |
| 9458 | + | |
| 9459 | + | |
| 9460 | + | |
| 9461 | + | |
| 9462 | + | |
| 9463 | + | |
| 9464 | + | |
| 9465 | + | |
| 9466 | + | |
| 9467 | + | |
| 9468 | + | |
| 9469 | + | |
| 9470 | + | |
| 9471 | + | |
| 9472 | + | |
| 9473 | + | |
| 9474 | + | |
| 9475 | + | |
| 9476 | + | |
| 9477 | + | |
| 9478 | + | |
| 9479 | + | |
| 9480 | + | |
| 9481 | + | |
| 9482 | + | |
| 9483 | + | |
| 9484 | + | |
| 9485 | + | |
| 9486 | + | |
| 9487 | + | |
| 9488 | + | |
| 9489 | + | |
| 9490 | + | |
| 9491 | + | |
| 9492 | + | |
| 9493 | + | |
| 9494 | + | |
| 9495 | + | |
9428 | 9496 | | |
9429 | 9497 | | |
9430 | 9498 | | |
| |||
0 commit comments