-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve base64 decoding performance #13574
base: master
Are you sure you want to change the base?
Improve base64 decoding performance #13574
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found some odd things in the code, such as unused assignments. See the line comments.
I've only looked a bit into the diff so far. It's better to iron this out before continuing the review.
Could you please give the implementation a polish to ensure better code quality?
I suppose ameba should point out some of the issues (but not all).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long wait. This slipped a bit through the cracks. 🙇
I have one comment on a suspicious piece of code that I missed before.
Besides, I'm concerned about introducing completely new API methods (.decode(IO, IO)
and .decode(Bytes, Bytes)
). Such additions should be proposed in a dedicated issue, including a discussion of their use cases.
And their implementation will need spec coverage.
So, I'd ask to remove these extra methods from this PR and create a proposal issue.
# Move the pointer by one byte until there is a valid base64 character | ||
while in_pos < in_size && in_ptr.value.in?(10_u8, 13_u8) | ||
in_pos &+= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems odd. Contrary to the comment, this loop does not move the pointer. It just increases in_pos
which is simple integer counter. Should this include in_ptr += 1
perhaps?
No problem, it's only a performance PR anyways.
Yeah, I totally understand that! |
Yeah, adding a |
This pull request improves base64 decoding performance, especially when writing to
IO
s.Additionally, more ways to decode base64 were added (IO to IO, Bytes to user-allocated Bytes).
For the benchmarks, I moved the new implementation into
src/base64.cr
but renamed it toBase64P
.Benchmark Code 1 (Comparison old vs new)
Benchmark Results 1 (Comparison old vs new)
Benchmark 2 (Throughput)
On my PC, I get 1.76GB/s of synthetic throughput.
Code:
As you can see from the first benchmark, the implementation itself is faster but the cost is higher than the previous algorithm. Still, that's in the nanosecons range so it doesn't matter all that much.
This contant time could also be reduced by changing the buffer size from
IO::DEFAULT_BUFFER_SIZE
to something lower.But since base64 is most often used for things like data embedding or JWT, this should not be a huge problem.