1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-06 09:01:01 +01:00

Improve base-32 hash decoding performance with reverse map

The changes include:

* Defining nix32Chars as a constexpr char[].
* Adding a constexpr std::array<unsigned char, 256> (reverseNix32Map) to map characters to their base-32 digit values at compile time.
* Replacing the slow character search loop with a direct lookup using reverseNix32Map.
* Removing std::once_flag/isBase32 logic in references.cc in favor of reverseNix32Map

Signed-off-by: Alexander V. Nikolaev <avn@avnik.info>
This commit is contained in:
Alexander V. Nikolaev 2025-08-03 18:03:47 +03:00
parent 51a32e4645
commit 4bfc007a7b
No known key found for this signature in database
GPG key ID: B8AF18ABCA6271D2
3 changed files with 20 additions and 18 deletions

View file

@ -72,7 +72,19 @@ static std::string printHash16(const Hash & hash)
}
// omitted: E O U T
const std::string nix32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
constexpr char nix32Chars[] = "0123456789abcdfghijklmnpqrsvwxyz";
constexpr const std::array<unsigned char, 256> reverseNix32Map = [] {
std::array<unsigned char, 256> map{};
for (size_t i = 0; i < map.size(); ++i)
map[i] = 0xFF; // invalid
for (unsigned char i = 0; i < 32; ++i)
map[static_cast<unsigned char>(nix32Chars[i])] = i;
return map;
}();
static std::string printHash32(const Hash & hash)
{
@ -217,12 +229,11 @@ Hash::Hash(std::string_view rest, HashAlgorithm algo, bool isSRI)
for (unsigned int n = 0; n < rest.size(); ++n) {
char c = rest[rest.size() - n - 1];
unsigned char digit;
for (digit = 0; digit < nix32Chars.size(); ++digit) /* !!! slow */
if (nix32Chars[digit] == c)
break;
if (digit >= 32)
throw BadHash("invalid base-32 hash '%s'", rest);
unsigned char digit = reverseNix32Map[static_cast<unsigned char>(c)];
if (digit == 0xFF)
throw BadHash("invalid base-32 hash: '%s'", rest);
unsigned int b = n * 5;
unsigned int i = b / 8;
unsigned int j = b % 8;