Repository navigation
avoid compiling regular expressions for algorithms at init - #122
Conversation
|
cc @thaJeztah @AkihiroSuda this cuts init time cost by half :) |
|
Needs DCO |
There was a problem hiding this comment.
🟡 Changes recommended
Digest validation now repeatedly computes hash size, causing a hot-path regression for BLAKE3.
1 open finding
What changed in this PR
Replaces initialization-time regular expressions with direct validation logic.
Changes:
- Adds manual algorithm-name and lowercase-hex validation.
- Simplifies registered algorithm state.
- Adds registration cases and validation benchmark coverage.
| File | Description |
|---|---|
algorithm.go |
Replaces regex validation with character checks. |
algorithm_test.go |
Expands algorithm-name test cases. |
digest_test.go |
Adds a digest validation benchmark. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Oops, fixed. |
RegisterAlgorithm compiled a regular expression for each algorithm,
such as ^[a-f0-9]{64}$ for SHA256, and the large repetition counts made
these costly to compile. Since Validate already checks the length,
checking for lowercase hex digits is enough.
algorithmRegexp was also compiled at init time for RegisterAlgorithm;
replace it with an equivalent hand-written check.
As measured by https://github.com/mvdan/benchinit:
│ old │ new │
│ sec/op │ sec/op vs base │
GithubComOpencontainersGoDigest 117.57µ ± 1% 55.07µ ± 3% -53.16% (p=0.000 n=10)
│ old │ new │
│ B/op │ B/op vs base │
GithubComOpencontainersGoDigest 73.258Ki ± 0% 9.586Ki ± 0% -86.91% (p=0.000 n=10)
│ old │ new │
│ allocs/op │ allocs/op vs base │
GithubComOpencontainersGoDigest 687.0 ± 0% 126.0 ± 0% -81.66% (p=0.000 n=10)
Validate, which used the per-algorithm regular expressions,
gets faster as well, as shown by a new benchmark:
│ old │ new │
│ sec/op │ sec/op vs base │
Validate-24 435.25n ± 21% 65.10n ± 4% -85.04% (p=0.000 n=8)
Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
|
Yep, should be fixed now... |
|
@AkihiroSuda friendly nudge :) is there anything else I should do here? |
|
I'm not a maintainer here, but this was discussed in today's OCI call and I just want to point out that this new function is validating the set of allowable characters for algorithms, not the actual list of supported algorithms, so the likelihood of that list ever changing is essentially zero and this is pretty much a free speedup. 👍 |
|
(and benchmarks are in the commit message) |
|
Oh! I saw this one fly by my notifications and wanted to look. Thanks @mvdan good seeing you here (big fan of your work and modules ❤️)
I took the liberty of copy/pasting it in the PR description (GitHub still doesn't understand that commit messages are part of the PR, and just as relevant, if not more, than the code changes).
Yup! And the replacement (IMO) is readable enough to make it a good replacement for the regex. Of many "bad" choices in this module; at least a good decision was to not export the regex, so 🎉 good to change the implementation. Which reminds me, I still want to try if the Go maintainers are open to offering |
thaJeztah
left a comment
There was a problem hiding this comment.
(that's an LGTM from me)
thanks!
|
@sudo-bmitch wanted to look at this one, or good to go? |
It's in my queue to look over, but not enough to block the merge. |

avoid compiling regular expressions for algorithms at init
RegisterAlgorithm compiled a regular expression for each algorithm,
such as ^[a-f0-9]{64}$ for SHA256, and the large repetition counts made
these costly to compile. Since Validate already checks the length,
checking for lowercase hex digits is enough.
algorithmRegexp was also compiled at init time for RegisterAlgorithm;
replace it with an equivalent hand-written check.
As measured by https://github.com/mvdan/benchinit:
Validate, which used the per-algorithm regular expressions,
gets faster as well, as shown by a new benchmark: