Skip to content

Commit e204e9e

Browse files
committed
buffer: optimize byteLength for short strings
PR-URL: #54345
1 parent 298ff4f commit e204e9e

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

src/node_buffer.cc

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "v8-fast-api-calls.h"
3636
#include "v8.h"
3737

38+
#include <stdint.h>
3839
#include <climits>
3940
#include <cstring>
4041
#include "nbytes.h"
@@ -752,13 +753,40 @@ uint32_t FastByteLengthUtf8(Local<Value> receiver,
752753
if (source.length > 128) {
753754
return simdutf::utf8_length_from_latin1(source.data, source.length);
754755
}
756+
755757
uint32_t length = source.length;
756-
uint32_t result = length;
757-
const uint8_t* data = reinterpret_cast<const uint8_t*>(source.data);
758-
for (uint32_t i = 0; i < length; ++i) {
759-
result += (data[i] >> 7);
758+
const auto input = reinterpret_cast<const uint8_t*>(source.data);
759+
760+
uint32_t answer = length;
761+
uint32_t i = 0;
762+
763+
auto pop = [](uint64_t v) {
764+
return static_cast<size_t>(((v >> 7) & UINT64_C(0x0101010101010101)) *
765+
UINT64_C(0x0101010101010101) >>
766+
56);
767+
};
768+
769+
for (; i + 32 <= length; i += 32) {
770+
uint64_t v;
771+
memcpy(&v, input + i, 8);
772+
answer += pop(v);
773+
memcpy(&v, input + i + 8, 8);
774+
answer += pop(v);
775+
memcpy(&v, input + i + 16, 8);
776+
answer += pop(v);
777+
memcpy(&v, input + i + 24, 8);
778+
answer += pop(v);
779+
}
780+
for (; i + 8 <= length; i += 8) {
781+
uint64_t v;
782+
memcpy(&v, input + i, 8);
783+
answer += pop(v);
760784
}
761-
return result;
785+
for (; i + 1 <= length; i += 1) {
786+
answer += input[i] >> 7;
787+
}
788+
789+
return answer;
762790
}
763791

764792
static v8::CFunction fast_byte_length_utf8(

0 commit comments

Comments
 (0)