Skip to content

Commit

Permalink
util: improve textdecoder decode performance
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Nov 3, 2022
1 parent f1e9382 commit 472ec5a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
19 changes: 19 additions & 0 deletions benchmark/util/text-decoder.js
@@ -0,0 +1,19 @@
'use strict';

const common = require('../common.js');

const bench = common.createBenchmark(main, {
encoding: ['utf-8', 'latin1', 'iso-8859-3'],
ignoreBOM: [0, 1],
len: [256, 1024 * 16, 1024 * 512],
n: [1e6]
});

function main({ encoding, len, n, ignoreBOM }) {
const buf = Buffer.allocUnsafe(len);
const decoder = new TextDecoder(encoding, { ignoreBOM });

bench.start();
decoder.decode(buf);
bench.end(n);
}
2 changes: 1 addition & 1 deletion lib/internal/encoding.js
Expand Up @@ -432,7 +432,7 @@ function makeTextDecoderICU() {
if (typeof ret === 'number') {
throw new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding, ret);
}
return ret.toString('ucs2');
return ret;
}
}

Expand Down
35 changes: 25 additions & 10 deletions src/node_i18n.cc
Expand Up @@ -50,6 +50,7 @@
#include "node_buffer.h"
#include "node_errors.h"
#include "node_internals.h"
#include "string_bytes.h"
#include "util-inl.h"
#include "v8.h"

Expand Down Expand Up @@ -502,18 +503,32 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
}
}
ret = ToBufferEndian(env, &result);
if (omit_initial_bom && !ret.IsEmpty()) {
// Perform `ret = ret.slice(2)`.

if (!ret.IsEmpty()) {
CHECK(ret.ToLocalChecked()->IsUint8Array());
Local<Uint8Array> orig_ret = ret.ToLocalChecked().As<Uint8Array>();
ret = Buffer::New(env,
orig_ret->Buffer(),
orig_ret->ByteOffset() + 2,
orig_ret->ByteLength() - 2)
.FromMaybe(Local<Uint8Array>());

if (omit_initial_bom) {
// Perform `ret = ret.slice(2)`.
Local<Uint8Array> orig_ret = ret.ToLocalChecked().As<Uint8Array>();
ret = Buffer::New(env,
orig_ret->Buffer(),
orig_ret->ByteOffset() + 2,
orig_ret->ByteLength() - 2)
.FromMaybe(Local<Uint8Array>());
}

Local<Value> error;
ArrayBufferViewContents<char> buf(ret.ToLocalChecked());
MaybeLocal<Value> encoded = StringBytes::Encode(
env->isolate(), buf.data(), buf.length(), encoding::UCS2, &error);

if (!encoded.IsEmpty()) {
args.GetReturnValue().Set(encoded.ToLocalChecked());
} else {
args.GetReturnValue().Set(error);
}
}
if (!ret.IsEmpty())
args.GetReturnValue().Set(ret.ToLocalChecked());

return;
}

Expand Down

0 comments on commit 472ec5a

Please sign in to comment.