Skip to content

Commit 4730850

Browse files
anonrigdanielleadams
authored andcommitted
util: improve textdecoder decode performance
PR-URL: #45294 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent e0a8eff commit 4730850

File tree

3 files changed

+47
-14
lines changed

3 files changed

+47
-14
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
@@ -438,7 +438,7 @@ function makeTextDecoderICU() {
438438
if (typeof ret === 'number') {
439439
throw new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding, ret);
440440
}
441-
return ret.toString('ucs2');
441+
return ret;
442442
}
443443
}
444444

src/node_i18n.cc

+27-13
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

@@ -96,7 +97,6 @@ using v8::NewStringType;
9697
using v8::Object;
9798
using v8::ObjectTemplate;
9899
using v8::String;
99-
using v8::Uint8Array;
100100
using v8::Value;
101101

102102
namespace i18n {
@@ -445,7 +445,6 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
445445

446446
UErrorCode status = U_ZERO_ERROR;
447447
MaybeStackBuffer<UChar> result;
448-
MaybeLocal<Object> ret;
449448

450449
UBool flush = (flags & CONVERTER_FLAGS_FLUSH) == CONVERTER_FLAGS_FLUSH;
451450

@@ -501,19 +500,34 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
501500
converter->set_bom_seen(true);
502501
}
503502
}
504-
ret = ToBufferEndian(env, &result);
505-
if (omit_initial_bom && !ret.IsEmpty()) {
503+
504+
Local<Value> error;
505+
UChar* output = result.out();
506+
size_t beginning = 0;
507+
size_t length = result.length() * sizeof(UChar);
508+
509+
if (omit_initial_bom) {
506510
// Perform `ret = ret.slice(2)`.
507-
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>());
511+
beginning += 2;
512+
length -= 2;
514513
}
515-
if (!ret.IsEmpty())
516-
args.GetReturnValue().Set(ret.ToLocalChecked());
514+
515+
char* value = reinterpret_cast<char*>(output) + beginning;
516+
517+
if (IsBigEndian()) {
518+
SwapBytes16(value, length);
519+
}
520+
521+
MaybeLocal<Value> encoded =
522+
StringBytes::Encode(env->isolate(), value, length, UCS2, &error);
523+
524+
Local<Value> ret;
525+
if (encoded.ToLocal(&ret)) {
526+
args.GetReturnValue().Set(ret);
527+
} else {
528+
args.GetReturnValue().Set(error);
529+
}
530+
517531
return;
518532
}
519533

0 commit comments

Comments
 (0)