Skip to content

Commit d87f9af

Browse files
tniessentargos
authored andcommitted
buffer: make compare/equals faster
This patch adds a V8 fast API implementation for the buffer.compare binding, which is used both by Buffer.prototype.equals and Buffer.prototype.compare. In particular, it significantly improves the performance of comparing buffers for equality. PR-URL: #52993 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Mohammed Keyvanzadeh <[email protected]>
1 parent 4347bd2 commit d87f9af

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/node_buffer.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ using v8::ArrayBufferView;
5757
using v8::BackingStore;
5858
using v8::Context;
5959
using v8::EscapableHandleScope;
60+
using v8::FastApiTypedArray;
6061
using v8::FunctionCallbackInfo;
6162
using v8::Global;
6263
using v8::HandleScope;
@@ -843,6 +844,23 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
843844
args.GetReturnValue().Set(val);
844845
}
845846

847+
int32_t FastCompare(v8::Local<v8::Value>,
848+
const FastApiTypedArray<uint8_t>& a,
849+
const FastApiTypedArray<uint8_t>& b) {
850+
uint8_t* data_a;
851+
uint8_t* data_b;
852+
CHECK(a.getStorageIfAligned(&data_a));
853+
CHECK(b.getStorageIfAligned(&data_b));
854+
855+
size_t cmp_length = std::min(a.length(), b.length());
856+
857+
return normalizeCompareVal(
858+
cmp_length > 0 ? memcmp(data_a, data_b, cmp_length) : 0,
859+
a.length(),
860+
b.length());
861+
}
862+
863+
static v8::CFunction fast_compare(v8::CFunction::Make(FastCompare));
846864

847865
// Computes the offset for starting an indexOf or lastIndexOf search.
848866
// Returns either a valid offset in [0...<length - 1>], ie inside the Buffer,
@@ -1409,7 +1427,7 @@ void Initialize(Local<Object> target,
14091427
SlowByteLengthUtf8,
14101428
&fast_byte_length_utf8);
14111429
SetMethod(context, target, "copy", Copy);
1412-
SetMethodNoSideEffect(context, target, "compare", Compare);
1430+
SetFastMethodNoSideEffect(context, target, "compare", Compare, &fast_compare);
14131431
SetMethodNoSideEffect(context, target, "compareOffset", CompareOffset);
14141432
SetMethod(context, target, "fill", Fill);
14151433
SetMethodNoSideEffect(context, target, "indexOfBuffer", IndexOfBuffer);
@@ -1469,6 +1487,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14691487
registry->Register(FastByteLengthUtf8);
14701488
registry->Register(Copy);
14711489
registry->Register(Compare);
1490+
registry->Register(FastCompare);
1491+
registry->Register(fast_compare.GetTypeInfo());
14721492
registry->Register(CompareOffset);
14731493
registry->Register(Fill);
14741494
registry->Register(IndexOfBuffer);

src/node_external_reference.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ using CFunctionCallbackWithStrings =
2727
bool (*)(v8::Local<v8::Value>,
2828
const v8::FastOneByteString& input,
2929
const v8::FastOneByteString& base);
30+
using CFunctionCallbackWithTwoUint8Arrays =
31+
int32_t (*)(v8::Local<v8::Value>,
32+
const v8::FastApiTypedArray<uint8_t>&,
33+
const v8::FastApiTypedArray<uint8_t>&);
3034
using CFunctionCallbackWithTwoUint8ArraysFallback =
3135
bool (*)(v8::Local<v8::Value>,
3236
const v8::FastApiTypedArray<uint8_t>&,
@@ -56,6 +60,7 @@ class ExternalReferenceRegistry {
5660
V(CFunctionCallbackWithBool) \
5761
V(CFunctionCallbackWithString) \
5862
V(CFunctionCallbackWithStrings) \
63+
V(CFunctionCallbackWithTwoUint8Arrays) \
5964
V(CFunctionCallbackWithTwoUint8ArraysFallback) \
6065
V(CFunctionWithUint32) \
6166
V(CFunctionWithDoubleReturnDouble) \

0 commit comments

Comments
 (0)