5x faster toString("base64url") (#11087)

This commit is contained in:
Jarred Sumner
2024-05-15 15:53:25 -07:00
committed by GitHub
parent b5dff55ef3
commit 9c5d339ccb
2 changed files with 19 additions and 45 deletions

View File

@@ -14,6 +14,14 @@ bench(`Buffer(${uuid.byteLength}).toString('base64')`, () => {
return uuid.toString("base64");
});
bench(`Buffer(${bigBuffer.byteLength}).toString('base64url')`, () => {
return bigBuffer.toString("base64url");
});
bench(`Buffer(${uuid.byteLength}).toString('base64url')`, () => {
return uuid.toString("base64url");
});
bench(`Buffer(${bigBuffer.byteLength}).toString('hex')`, () => {
return bigBuffer.toString("hex");
});

View File

@@ -5,6 +5,7 @@
#include <wtf/dtoa.h>
#include <atomic>
#include "simdutf.h"
#if OS(WINDOWS)
#include <uv.h>
#endif
@@ -170,57 +171,20 @@ extern "C" int Bun__ttySetMode(int fd, int mode)
extern "C" double WTF__parseDouble(const LChar* string, size_t length, size_t* position)
{
return WTF::parseDouble({string, length}, *position);
return WTF::parseDouble({ string, length }, *position);
}
extern "C" void WTF__copyLCharsFromUCharSource(LChar* destination, const UChar* source, size_t length)
{
WTF::StringImpl::copyCharacters(destination, {source, length});
WTF::StringImpl::copyCharacters(destination, { source, length });
}
// For whatever reason
// Doing this in C++/C is 2x faster than doing it in Zig.
// However, it's still slower than it should be.
static constexpr size_t encodeMapSize = 64;
static constexpr char base64URLEncMap[encodeMapSize] = {
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F
};
extern "C" size_t WTF__base64URLEncode(const unsigned char* __restrict inputDataBuffer, size_t inputDataBufferSize,
unsigned char* __restrict destinationDataBuffer,
extern "C" size_t WTF__base64URLEncode(const char* __restrict inputDataBuffer, size_t inputDataBufferSize,
char* __restrict destinationDataBuffer,
size_t destinationDataBufferSize)
{
size_t sidx = 0;
size_t didx = 0;
if (inputDataBufferSize > 1) {
while (sidx < inputDataBufferSize - 2) {
destinationDataBuffer[didx++] = base64URLEncMap[(inputDataBuffer[sidx] >> 2) & 077];
destinationDataBuffer[didx++] = base64URLEncMap[((inputDataBuffer[sidx + 1] >> 4) & 017) | ((inputDataBuffer[sidx] << 4) & 077)];
destinationDataBuffer[didx++] = base64URLEncMap[((inputDataBuffer[sidx + 2] >> 6) & 003) | ((inputDataBuffer[sidx + 1] << 2) & 077)];
destinationDataBuffer[didx++] = base64URLEncMap[inputDataBuffer[sidx + 2] & 077];
sidx += 3;
}
}
if (sidx < inputDataBufferSize) {
destinationDataBuffer[didx++] = base64URLEncMap[(inputDataBuffer[sidx] >> 2) & 077];
if (sidx < inputDataBufferSize - 1) {
destinationDataBuffer[didx++] = base64URLEncMap[((inputDataBuffer[sidx + 1] >> 4) & 017) | ((inputDataBuffer[sidx] << 4) & 077)];
destinationDataBuffer[didx++] = base64URLEncMap[(inputDataBuffer[sidx + 1] << 2) & 077];
} else
destinationDataBuffer[didx++] = base64URLEncMap[(inputDataBuffer[sidx] << 4) & 077];
}
while (didx < destinationDataBufferSize)
destinationDataBuffer[didx++] = '=';
return destinationDataBufferSize;
UNUSED_PARAM(destinationDataBufferSize);
return simdutf::binary_to_base64(inputDataBuffer, inputDataBufferSize, destinationDataBuffer, simdutf::base64_url);
}
namespace Bun {
@@ -237,8 +201,10 @@ String base64URLEncodeToString(Vector<uint8_t> data)
RELEASE_ASSERT_NOT_REACHED();
return String();
}
encodedLength = WTF__base64URLEncode(data.data(), data.size(), ptr, encodedLength);
RELEASE_ASSERT(result.length() == encodedLength);
encodedLength = WTF__base64URLEncode(reinterpret_cast<const char*>(data.data()), data.size(), reinterpret_cast<char*>(ptr), encodedLength);
if (result.length() != encodedLength) {
return result.substringSharingImpl(0, encodedLength);
}
return result;
}