Skip to content

Commit f36831f

Browse files
ronagtargos
authored andcommitted
buffer: optimize createFromString
PR-URL: #54324 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 2859b4b commit f36831f

File tree

2 files changed

+29
-31
lines changed

2 files changed

+29
-31
lines changed

lib/buffer.js

+29-18
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ const {
5757
byteLengthUtf8,
5858
compare: _compare,
5959
compareOffset,
60-
createFromString,
6160
fill: bindingFill,
6261
isAscii: bindingIsAscii,
6362
isUtf8: bindingIsUtf8,
@@ -148,11 +147,12 @@ const constants = ObjectDefineProperties({}, {
148147
});
149148

150149
Buffer.poolSize = 8 * 1024;
151-
let poolSize, poolOffset, allocPool;
150+
let poolSize, poolOffset, allocPool, allocBuffer;
152151

153152
function createPool() {
154153
poolSize = Buffer.poolSize;
155-
allocPool = createUnsafeBuffer(poolSize).buffer;
154+
allocBuffer = createUnsafeBuffer(poolSize);
155+
allocPool = allocBuffer.buffer;
156156
markAsUntransferable(allocPool);
157157
poolOffset = 0;
158158
}
@@ -440,38 +440,49 @@ function allocate(size) {
440440
}
441441

442442
function fromStringFast(string, ops) {
443-
const length = ops.byteLength(string);
443+
const maxLength = Buffer.poolSize >>> 1;
444444

445-
if (length >= (Buffer.poolSize >>> 1))
446-
return createFromString(string, ops.encodingVal);
445+
let length = string.length; // Min length
446+
447+
if (length >= maxLength)
448+
return createFromString(string, ops);
449+
450+
length *= 4; // Max length (4 bytes per character)
451+
452+
if (length >= maxLength)
453+
length = ops.byteLength(string); // Actual length
454+
455+
if (length >= maxLength)
456+
return createFromString(string, ops, length);
447457

448458
if (length > (poolSize - poolOffset))
449459
createPool();
450-
let b = new FastBuffer(allocPool, poolOffset, length);
451-
const actual = ops.write(b, string, 0, length);
452-
if (actual !== length) {
453-
// byteLength() may overestimate. That's a rare case, though.
454-
b = new FastBuffer(allocPool, poolOffset, actual);
455-
}
460+
461+
const actual = ops.write(allocBuffer, string, poolOffset, length);
462+
const b = new FastBuffer(allocPool, poolOffset, actual);
463+
456464
poolOffset += actual;
457465
alignPool();
458466
return b;
459467
}
460468

469+
function createFromString(string, ops, length = ops.byteLength(string)) {
470+
const buf = Buffer.allocUnsafeSlow(length);
471+
const actual = ops.write(buf, string, 0, length);
472+
return actual < length ? new FastBuffer(buf.buffer, 0, actual) : buf;
473+
}
474+
461475
function fromString(string, encoding) {
462476
let ops;
463-
if (typeof encoding !== 'string' || encoding.length === 0) {
464-
if (string.length === 0)
465-
return new FastBuffer();
477+
if (!encoding || encoding === 'utf8') {
466478
ops = encodingOps.utf8;
467479
} else {
468480
ops = getEncodingOps(encoding);
469481
if (ops === undefined)
470482
throw new ERR_UNKNOWN_ENCODING(encoding);
471-
if (string.length === 0)
472-
return new FastBuffer();
473483
}
474-
return fromStringFast(string, ops);
484+
485+
return string.length === 0 ? new FastBuffer() : fromStringFast(string, ops);
475486
}
476487

477488
function fromArrayBuffer(obj, byteOffset, length) {

src/node_buffer.cc

-13
Original file line numberDiff line numberDiff line change
@@ -529,17 +529,6 @@ MaybeLocal<Object> New(Environment* env,
529529

530530
namespace {
531531

532-
void CreateFromString(const FunctionCallbackInfo<Value>& args) {
533-
CHECK(args[0]->IsString());
534-
CHECK(args[1]->IsInt32());
535-
536-
enum encoding enc = static_cast<enum encoding>(args[1].As<Int32>()->Value());
537-
Local<Object> buf;
538-
if (New(args.GetIsolate(), args[0].As<String>(), enc).ToLocal(&buf))
539-
args.GetReturnValue().Set(buf);
540-
}
541-
542-
543532
template <encoding encoding>
544533
void StringSlice(const FunctionCallbackInfo<Value>& args) {
545534
Environment* env = Environment::GetCurrent(args);
@@ -1422,7 +1411,6 @@ void Initialize(Local<Object> target,
14221411
SetMethodNoSideEffect(context, target, "btoa", Btoa);
14231412

14241413
SetMethod(context, target, "setBufferPrototype", SetBufferPrototype);
1425-
SetMethodNoSideEffect(context, target, "createFromString", CreateFromString);
14261414

14271415
SetFastMethodNoSideEffect(context,
14281416
target,
@@ -1487,7 +1475,6 @@ void Initialize(Local<Object> target,
14871475

14881476
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14891477
registry->Register(SetBufferPrototype);
1490-
registry->Register(CreateFromString);
14911478

14921479
registry->Register(SlowByteLengthUtf8);
14931480
registry->Register(fast_byte_length_utf8.GetTypeInfo());

0 commit comments

Comments
 (0)