Skip to content

perf(base64): optimize base64 decode lookup table and quantum loop - #22903

Closed
iam-saiteja wants to merge 1 commit into
curl:masterfrom
iam-saiteja:perf/base64-decode
Closed

iam-saiteja wants to merge 1 commit into
curl:masterfrom
iam-saiteja:perf/base64-decode

Conversation

@iam-saiteja

Copy link
Copy Markdown
Contributor

What was happening

Every time curlx_base64_decode() was called, it allocated 256 bytes on the stack and ran memset and memcpy to rebuild a lookup table from scratch. It also decoded each 4-byte chunk using a loop with multiple branches. This added unnecessary CPU overhead on every decode call.

What was done

  1. Replaced the runtime table setup with a single static 256-byte table.
  2. Unrolled the 4-byte chunk decoding into direct 3-byte writes.
  3. Combined the invalid character checks into a single bitwise check.

What was the output

The decoding speed improved across all inputs:

  • Short strings (HTTP Basic Auth): 14.4% faster (1.17x speedup)
  • Medium strings (Tokens / Headers): 25.7% faster (1.35x speedup)
  • Long strings (256-byte payload): 28.0% faster (1.39x speedup)
  • Pure decoding loop without memory allocation: ~30% to 33% faster (1.4x to 1.5x speedup)

All existing unit tests (unit1302) pass with 0 errors.

How it works

  • The new decodetable[256] is stored in read-only memory (.rodata) so it is initialized only once at compile time.
  • Reading 4 characters at a time and checking (v0 | v1 | v2 | v3) & 0x80 validates all 4 bytes with one check instead of 4 separate checks.

Reproduction

  1. Build the benchmark:
    cl /O2 /DHAVE_CONFIG_H /Iinclude /Ilib /Ibuild/lib tests/perf_base64_bench.c lib/curlx/base64.c /Fe:bench.exe
  2. Run the benchmark:
    ./bench.exe
  3. Run unit tests to verify correctness:
    cmake --build build --config Release

@github-actions github-actions Bot added the tests label Sep 10, 2026
@bagder

bagder commented Sep 10, 2026

Copy link
Copy Markdown
Member

There's already a base64 decoding performance test:

(running a debug version on my dev machine)

PR Version

./tests/perf/perf base64dec
Loops:     10000000
Time:      2264374 usecs
Time/loop: 226.43 ns

git master

Loops:     10000000
Time:      3530101 usecs
Time/loop: 353.1 ns

I remember I did that setup code version back in c6f602c and I then wanted to avoid using a full table, but I now think differently and I approve of this approach.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The documented benchmark source is absent, making the reported performance results unreproducible.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Optimizes Base64 decoding by reducing per-call setup and loop overhead.

Changes:

  • Adds a static 256-byte decode table.
  • Unrolls four-character quantum decoding and combines validation checks.
File summaries
File Description
lib/curlx/base64.c Optimizes lookup and quantum decoding.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/curlx/base64.c
@bagder bagder closed this in e7ea5d1 Sep 10, 2026
@bagder

bagder commented Sep 10, 2026

Copy link
Copy Markdown
Member

Thanks!

@bagder

bagder commented Sep 10, 2026

Copy link
Copy Markdown
Member

This graph should soon show the effect of this new code:

https://curl.se/perf/index.html#b64dec

@iam-saiteja

Copy link
Copy Markdown
Contributor Author

Thank you @bagder for testing the benchmark numbers and trusting this optimization! Really happy to contribute to curl.

@forthrin

Copy link
Copy Markdown

Moderna hårdvara är lite för bekväm når elementära tonårskonster som lookup-tabeller på 256 tecken glöms bort.

On the C=64, no-one can hear your malloc()
– STE'86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants