Roblox will automatically encode buffers using zbase64 which is 1000x faster because the backend is done in c++
--!native
--!optimize 2
local HttpService = game:GetService("HttpService")
local Offset = 34
local function Encode(Text)
local Encoded = HttpService:JSONEncode(Text)
local Buffer = buffer.fromstring(Encoded)
local Length = buffer.len(Buffer)
local Base64Length = Length - Offset - 2
local Base64Buffer = buffer.create(Base64Length)
buffer.copy(Base64Buffer, 0, Buffer, Offset, Base64Length)
return buffer.tostring(Base64Buffer)
end
local TestString = buffer.fromstring(string.rep("h", 1e6))
local Start = os.clock()
for _ = 1, 1e3 do
local _ = Encode(TestString)
end
warn(`Benchmark: ${os.clock() - Start} seconds`) -- around 0.1 seconds
You can just work with the JSONEncode string directly.
local function Encode(Input: buffer): string
return string.sub(HttpService:JSONEncode(Input), 34, -3)
end
local function Decode(Input: string): buffer
return HttpService:JSONDecode("{\"m\":null,\"t\":\"buffer\",\"base64\":\"" .. Input .. "\"}")
end
Granted, a faster implementation is probably feasible with native calls to buffer.readbits/writebits, but this is definitely the simplest one.
You’re right. I ran a benchmark using a 1000-byte string over 1000 iterations:
Base64.encode: 0.0973 s
JSONEncode(buffer): 0.0047 s
JSONEncode(buffer) + slice: 0.0046 s
The native method is a lot faster, since it’s handled in C++. That said, my goal with this module, was something:
that doesn’t rely on the buffer API,
and is fully transparent, and easy to modify.
It’s mainly for cases where you need reliable Base64 encoding for strings or byte arrays.
Might add an optional buffer-based path later for those who want the speed boost.
Thanks.
Well yes if the string is too long then its a dev problem, it won’t even get past the luau error of long strings with the 1gb limit. You can always process it in chunks
I wrote that in devfourm as an example, you’d be better off doing something like
local HttpService = game:GetService("HttpService")
local ToString = buffer.tostring
local FromString = buffer.fromstring
local function Compress(Text)
return HttpService:JSONEncode(FromString(Text))
end
local function Decompress(Text)
return ToString(HttpService:JSONDecode(Text))
end
return {
Compress = Compress,
Decompress = Decompress
}
Unless you want to create a way to process a string in chunks less than a 100, theres no real way to change it back into normal base64 as I believe the internal compression is custom
local HttpService = game:GetService("HttpService")
local Offset = 34
local function Encode(Text : string) : string
local Encoded = HttpService:JSONEncode(buffer.fromstring(Text))
local Buffer = buffer.fromstring(Encoded)
local Length = buffer.len(Buffer)
local Base64Length = Length - Offset - 2
local Base64Buffer = buffer.create(Base64Length)
buffer.copy(Base64Buffer, 0, Buffer, Offset, Base64Length)
return buffer.tostring(Base64Buffer)
end
local function Decode(Text : string) : string
return buffer.tostring(HttpService:JSONDecode(`\{"m":null,"t":"buffer","{Text:match("^KLUv/") and "zbase64" or "base64"}":"{Text}"\}`))
end