Skip to content

Commit 472ec5a

Browse files
committed
util: improve textdecoder decode performance
1 parent f1e9382 commit 472ec5a

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

benchmark/util/text-decoder.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
5+
const bench = common.createBenchmark(main, {
6+
encoding: ['utf-8', 'latin1', 'iso-8859-3'],
7+
ignoreBOM: [0, 1],
8+
len: [256, 1024 * 16, 1024 * 512],
9+
n: [1e6]
10+
});
11+
12+
function main({ encoding, len, n, ignoreBOM }) {
13+
const buf = Buffer.allocUnsafe(len);
14+
const decoder = new TextDecoder(encoding, { ignoreBOM });
15+
16+
bench.start();
17+
decoder.decode(buf);
18+
bench.end(n);
19+
}

lib/internal/encoding.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ function makeTextDecoderICU() {
432432
if (typeof ret === 'number') {
433433
throw new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding, ret);
434434
}
435-
return ret.toString('ucs2');
435+
return ret;
436436
}
437437
}
438438

src/node_i18n.cc

+25-10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "node_buffer.h"
5151
#include "node_errors.h"
5252
#include "node_internals.h"
53+
#include "string_bytes.h"
5354
#include "util-inl.h"
5455
#include "v8.h"
5556

@@ -502,18 +503,32 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
502503
}
503504
}
504505
ret = ToBufferEndian(env, &result);
505-
if (omit_initial_bom && !ret.IsEmpty()) {
506-
// Perform `ret = ret.slice(2)`.
506+
507+
if (!ret.IsEmpty()) {
507508
CHECK(ret.ToLocalChecked()->IsUint8Array());
508-
Local<Uint8Array> orig_ret = ret.ToLocalChecked().As<Uint8Array>();
509-
ret = Buffer::New(env,
510-
orig_ret->Buffer(),
511-
orig_ret->ByteOffset() + 2,
512-
orig_ret->ByteLength() - 2)
513-
.FromMaybe(Local<Uint8Array>());
509+
510+
if (omit_initial_bom) {
511+
// Perform `ret = ret.slice(2)`.
512+
Local<Uint8Array> orig_ret = ret.ToLocalChecked().As<Uint8Array>();
513+
ret = Buffer::New(env,
514+
orig_ret->Buffer(),
515+
orig_ret->ByteOffset() + 2,
516+
orig_ret->ByteLength() - 2)
517+
.FromMaybe(Local<Uint8Array>());
518+
}
519+
520+
Local<Value> error;
521+
ArrayBufferViewContents<char> buf(ret.ToLocalChecked());
522+
MaybeLocal<Value> encoded = StringBytes::Encode(
523+
env->isolate(), buf.data(), buf.length(), encoding::UCS2, &error);
524+
525+
if (!encoded.IsEmpty()) {
526+
args.GetReturnValue().Set(encoded.ToLocalChecked());
527+
} else {
528+
args.GetReturnValue().Set(error);
529+
}
514530
}
515-
if (!ret.IsEmpty())
516-
args.GetReturnValue().Set(ret.ToLocalChecked());
531+
517532
return;
518533
}
519534

0 commit comments

Comments
 (0)