TextDecoderOnlySmall

Benchmark created on


Setup

const utf8Decoder = new TextDecoder();
const data = new Uint8Array(100_000);

for (var i = 0; i < data.length;) {
  // Initialize to a repeated sequence of
  // "xx€" to test both 1-byte and 3-byte
  // utf8 decoding performance.
  data[i++] = 120;  // 'x'
  data[i++] = 120;  // 'x'
  data[i++] = 226;  // '€' byte 1
  data[i++] = 130;  // '€' byte 2
  data[i++] = 172;  // '€' byte 3
}

function DecodeUtf8(array, start, length) {
  if (length === 0) return "";
  if (length === 1) return String.fromCharCode(array[start]);
  let codes = new Array(length);
  let written = 0;
  let end = start + length;
  while (start < end) {
    let c = array[start++];
    if (c <= 0x7F) {
      codes[written++] = c;
    } else if (c <= 0xDF) {
      let c2 = array[start++];
      codes[written++] = ((c & 0x1F) << 6) | (c2 & 0x3F);
    } else if (c <= 0xEF) {
      let c2 = array[start++];
      let c3 = array[start++];
      codes[written++] = ((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F);
    } else if (c <= 0xF7) {
      let c2 = array[start++];
      let c3 = array[start++];
      let c4 = array[start++];
      let utf32 = ((c & 0x7) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) |
          (c4 & 0x3F);
      utf32 -= 0x10000;
      codes[written++] = 0xD800 + (utf32 >> 10);
      codes[written++] = 0xDC00 + (utf32 & 0x3FF);
    } else {
      throw "invalid utf8";
    }
  }
  if (written + 40 < codes.length) {
    codes.length = written;
  } else {
    while (written < codes.length) codes.pop();
  }
  return String.fromCharCode.apply(null, codes);
}

Test runner

Ready to run.

Testing in
TestOps/sec
Small Calls
var results = [];
var ofs = 0;
for (var i = 0; i < 10_000; i++, ofs += 10) {
  results.push(utf8Decoder.decode(data.subarray(ofs, ofs + 10)));
}
if (results.length != 10_000) throw "bad";
ready
empty
const i = 8;
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.