From 77e8d443acd9b31ea174a146ab4dd03bd30b50e6 Mon Sep 17 00:00:00 2001 From: Nikita Skovoroda Date: Wed, 21 Jan 2026 21:40:17 +0300 Subject: [PATCH] src: improve StringBytes::Encode perf on UTF8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gürgün Dayıoğlu PR-URL: https://github.com/nodejs/node/pull/61131 Reviewed-By: Gürgün Dayıoğlu Reviewed-By: Stephen Belanger Reviewed-By: Matteo Collina Reviewed-By: Daniel Lemire Reviewed-By: Anna Henningsen Reviewed-By: Rafael Gonzaga --- src/encoding_binding.cc | 2 ++ src/string_bytes.cc | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc index 1506442f704..7683d205aa6 100644 --- a/src/encoding_binding.cc +++ b/src/encoding_binding.cc @@ -379,6 +379,8 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo& args) { return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA( env->isolate(), "The encoded data was not valid for encoding utf-8"); } + + // TODO(chalker): save on utf8 validity recheck in StringBytes::Encode() } if (length == 0) return args.GetReturnValue().SetEmptyString(); diff --git a/src/string_bytes.cc b/src/string_bytes.cc index 8f6bedd63e2..6341346da07 100644 --- a/src/string_bytes.cc +++ b/src/string_bytes.cc @@ -539,6 +539,25 @@ MaybeLocal StringBytes::Encode(Isolate* isolate, return ExternOneByteString::NewFromCopy(isolate, buf, buflen); } + if (buflen >= 32 && simdutf::validate_utf8(buf, buflen)) { + // We know that we are non-ASCII (and are unlikely Latin1), use 2-byte + // In the most likely case of valid UTF-8, we can use this fast impl + // For very short input, it is slower, so we limit min size + size_t u16size = simdutf::utf16_length_from_utf8(buf, buflen); + if (u16size > static_cast(v8::String::kMaxLength)) { + isolate->ThrowException(ERR_STRING_TOO_LONG(isolate)); + return MaybeLocal(); + } + uint16_t* dst = node::UncheckedMalloc(u16size); + if (u16size != 0 && dst == nullptr) { + THROW_ERR_MEMORY_ALLOCATION_FAILED(isolate); + return MaybeLocal(); + } + size_t utf16len = simdutf::convert_valid_utf8_to_utf16( + buf, buflen, reinterpret_cast(dst)); + return ExternTwoByteString::New(isolate, dst, utf16len); + } + val = String::NewFromUtf8(isolate, buf, v8::NewStringType::kNormal, buflen); Local str;