This is a kind of tragedy that TextDecoder is not always the best way. I wish someday when these complex conditions are completely obsolete, but for now, this is the best.
$ npx ts-node benchmark/decode-string.ts
## string "A" x 10 (byteLength=10)
utf8DecodeJs x 6,820,213 ops/sec ±5.21% (82 runs sampled)
utf8DecodeWasm x 1,030,221 ops/sec ±3.86% (81 runs sampled)
TextDecoder x 788,986 ops/sec ±2.04% (79 runs sampled)
## string "A" x 100 (byteLength=100)
utf8DecodeJs x 825,191 ops/sec ±1.89% (86 runs sampled)
utf8DecodeWasm x 507,129 ops/sec ±2.98% (81 runs sampled)
TextDecoder x 495,937 ops/sec ±10.66% (66 runs sampled)
## string "A" x 200 (byteLength=200)
utf8DecodeJs x 406,791 ops/sec ±3.24% (80 runs sampled)
utf8DecodeWasm x 339,505 ops/sec ±3.38% (83 runs sampled)
TextDecoder x 485,291 ops/sec ±2.81% (76 runs sampled)
## string "A" x 1000 (byteLength=1000)
utf8DecodeJs x 65,969 ops/sec ±4.95% (69 runs sampled)
utf8DecodeWasm x 83,295 ops/sec ±3.22% (76 runs sampled)
TextDecoder x 260,622 ops/sec ±4.55% (83 runs sampled)
## string "A" x 10000 (byteLength=10000)
utf8DecodeJs x 8,696 ops/sec ±2.89% (81 runs sampled)
utf8DecodeWasm x 9,953 ops/sec ±3.42% (82 runs sampled)
TextDecoder x 45,540 ops/sec ±4.64% (82 runs sampled)
## string "A" x 100000 (byteLength=100000)
utf8DecodeJs x 408 ops/sec ±4.20% (83 runs sampled)
utf8DecodeWasm x 84.42 ops/sec ±3.50% (72 runs sampled)
TextDecoder x 3,443 ops/sec ±4.34% (80 runs sampled)
## string "あ" x 10 (byteLength=30)
utf8DecodeJs x 4,456,073 ops/sec ±4.75% (75 runs sampled)
utf8DecodeWasm x 1,030,237 ops/sec ±3.24% (86 runs sampled)
TextDecoder x 626,129 ops/sec ±5.00% (70 runs sampled)
## string "あ" x 100 (byteLength=300)
utf8DecodeJs x 512,368 ops/sec ±9.75% (75 runs sampled)
utf8DecodeWasm x 423,180 ops/sec ±5.45% (80 runs sampled)
TextDecoder x 390,576 ops/sec ±2.21% (81 runs sampled)
## string "あ" x 200 (byteLength=600)
utf8DecodeJs x 339,130 ops/sec ±0.90% (93 runs sampled)
utf8DecodeWasm x 347,386 ops/sec ±2.08% (90 runs sampled)
TextDecoder x 250,218 ops/sec ±4.65% (77 runs sampled)
## string "あ" x 1000 (byteLength=3000)
utf8DecodeJs x 54,151 ops/sec ±7.31% (75 runs sampled)
utf8DecodeWasm x 71,328 ops/sec ±9.33% (75 runs sampled)
TextDecoder x 62,094 ops/sec ±7.82% (68 runs sampled)
## string "あ" x 10000 (byteLength=30000)
utf8DecodeJs x 6,474 ops/sec ±2.55% (87 runs sampled)
utf8DecodeWasm x 9,338 ops/sec ±1.50% (90 runs sampled)
TextDecoder x 8,195 ops/sec ±2.76% (89 runs sampled)
## string "あ" x 100000 (byteLength=300000)
utf8DecodeJs x 372 ops/sec ±3.82% (80 runs sampled)
utf8DecodeWasm x 85.82 ops/sec ±2.21% (73 runs sampled)
TextDecoder x 895 ops/sec ±1.22% (89 runs sampled)
## string "🌏" x 20 (byteLength=40)
utf8DecodeJs x 2,951,171 ops/sec ±1.22% (91 runs sampled)
utf8DecodeWasm x 732,553 ops/sec ±7.60% (72 runs sampled)
TextDecoder x 511,127 ops/sec ±9.85% (59 runs sampled)
## string "🌏" x 200 (byteLength=400)
utf8DecodeJs x 140,319 ops/sec ±16.40% (39 runs sampled)
utf8DecodeWasm x 255,222 ops/sec ±9.40% (74 runs sampled)
TextDecoder x 320,214 ops/sec ±4.21% (77 runs sampled)
## string "🌏" x 400 (byteLength=800)
utf8DecodeJs x 169,404 ops/sec ±6.21% (83 runs sampled)
utf8DecodeWasm x 176,243 ops/sec ±5.15% (79 runs sampled)
TextDecoder x 177,882 ops/sec ±10.15% (67 runs sampled)
## string "🌏" x 2000 (byteLength=4000)
utf8DecodeJs x 26,572 ops/sec ±6.99% (71 runs sampled)
utf8DecodeWasm x 43,111 ops/sec ±3.76% (80 runs sampled)
TextDecoder x 52,740 ops/sec ±5.80% (75 runs sampled)
## string "🌏" x 20000 (byteLength=40000)
utf8DecodeJs x 3,234 ops/sec ±4.96% (75 runs sampled)
utf8DecodeWasm x 4,254 ops/sec ±4.55% (80 runs sampled)
TextDecoder x 5,502 ops/sec ±3.99% (78 runs sampled)
## string "🌏" x 200000 (byteLength=400000)
utf8DecodeJs x 176 ops/sec ±6.27% (68 runs sampled)
utf8DecodeWasm x 33.61 ops/sec ±6.59% (44 runs sampled)
TextDecoder x 546 ops/sec ±4.38% (79 runs sampled)
Uh oh!
There was an error while loading. Please reload this page.
This is a kind of tragedy that TextDecoder is not always the best way. I wish someday when these complex conditions are completely obsolete, but for now, this is the best.
benchmark results: