From 7b641bc2bdcae8ac6b777b2f9d9eda4e0fc0144a Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 14 Aug 2024 23:22:13 +0200 Subject: [PATCH] buffer: optimize byteLength for short strings PR-URL: https://github.com/nodejs/node/pull/54345 Reviewed-By: Daniel Lemire Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- src/node_buffer.cc | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index d8fce1a8e8106a..ad700b6fbc027e 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -35,6 +35,7 @@ #include "v8-fast-api-calls.h" #include "v8.h" +#include #include #include #include "nbytes.h" @@ -741,13 +742,40 @@ uint32_t FastByteLengthUtf8(Local receiver, if (source.length > 128) { return simdutf::utf8_length_from_latin1(source.data, source.length); } + uint32_t length = source.length; - uint32_t result = length; - const uint8_t* data = reinterpret_cast(source.data); - for (uint32_t i = 0; i < length; ++i) { - result += (data[i] >> 7); + const auto input = reinterpret_cast(source.data); + + uint32_t answer = length; + uint32_t i = 0; + + auto pop = [](uint64_t v) { + return static_cast(((v >> 7) & UINT64_C(0x0101010101010101)) * + UINT64_C(0x0101010101010101) >> + 56); + }; + + for (; i + 32 <= length; i += 32) { + uint64_t v; + memcpy(&v, input + i, 8); + answer += pop(v); + memcpy(&v, input + i + 8, 8); + answer += pop(v); + memcpy(&v, input + i + 16, 8); + answer += pop(v); + memcpy(&v, input + i + 24, 8); + answer += pop(v); + } + for (; i + 8 <= length; i += 8) { + uint64_t v; + memcpy(&v, input + i, 8); + answer += pop(v); } - return result; + for (; i + 1 <= length; i += 1) { + answer += input[i] >> 7; + } + + return answer; } static v8::CFunction fast_byte_length_utf8(