Skip to content

Commit de2287e

Browse files
committed
buffer: port byteLengthUtf8 to JavaScript
Prior to this change the majority of the time spent when calling `Buffer.byteLength` was spent on crossing JS->C++ boundary. This change move the function to JavaScript, making it much faster.
1 parent 2313424 commit de2287e

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

lib/buffer.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
'use strict';
2323

2424
const {
25-
byteLengthUtf8,
2625
copy: _copy,
2726
compare: _compare,
2827
compareOffset,
@@ -320,6 +319,42 @@ function allocate(size) {
320319
}
321320

322321

322+
// Ported from deps/v8/src/unicode-inl.h
323+
function isTrailSurrogate(code) {
324+
return (code & 0xfc00) === 0xdc00;
325+
}
326+
327+
328+
function isLeadSurrogate(code) {
329+
// No previous character
330+
if (code === -1) return false;
331+
return (code & 0xfc00) === 0xd800;
332+
}
333+
334+
335+
function byteLengthUtf8(string) {
336+
var len = 0;
337+
var previous = -1;
338+
for (var i = 0; i < string.length; i++) {
339+
// NOTE: 0 <= code <= 0xffff
340+
var code = string.charCodeAt(i);
341+
if (code <= 0x7f) {
342+
len++;
343+
} else if (code <= 0x7ff) {
344+
len += 2;
345+
} else {
346+
// kSizeOfUnmatchedSurrogate - kBytesSavedByCombiningSurrogates
347+
if (isTrailSurrogate(code) && isLeadSurrogate(previous))
348+
len += 1;
349+
else
350+
len += 3;
351+
}
352+
previous = code;
353+
}
354+
return len;
355+
}
356+
357+
323358
function fromString(string, encoding) {
324359
var length;
325360
if (typeof encoding !== 'string' || encoding.length === 0) {

src/node_buffer.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,6 @@ void WriteDoubleBE(const FunctionCallbackInfo<Value>& args) {
785785
}
786786

787787

788-
void ByteLengthUtf8(const FunctionCallbackInfo<Value> &args) {
789-
CHECK(args[0]->IsString());
790-
791-
// Fast case: avoid StringBytes on UTF8 string. Jump to v8.
792-
args.GetReturnValue().Set(args[0].As<String>()->Utf8Length());
793-
}
794-
795788
// Normalize val to be an integer in the range of [1, -1] since
796789
// implementations of memcmp() can vary by platform.
797790
static int normalizeCompareVal(int val, size_t a_length, size_t b_length) {
@@ -1214,7 +1207,6 @@ void Initialize(Local<Object> target,
12141207
env->SetMethod(target, "setupBufferJS", SetupBufferJS);
12151208
env->SetMethod(target, "createFromString", CreateFromString);
12161209

1217-
env->SetMethod(target, "byteLengthUtf8", ByteLengthUtf8);
12181210
env->SetMethod(target, "copy", Copy);
12191211
env->SetMethod(target, "compare", Compare);
12201212
env->SetMethod(target, "compareOffset", CompareOffset);

0 commit comments

Comments
 (0)