diff --git a/src/spawn/ResourceLimits.cxx b/src/spawn/ResourceLimits.cxx index 516f68e1..7f4b2ecc 100644 --- a/src/spawn/ResourceLimits.cxx +++ b/src/spawn/ResourceLimits.cxx @@ -5,10 +5,9 @@ #include "ResourceLimits.hxx" #include "lib/fmt/SystemError.hxx" #include "util/Base32.hxx" -#include "util/djb_hash.hxx" #include "util/CharUtil.hxx" +#include "util/IntHash.hxx" #include "util/Sanitizer.hxx" -#include "util/SpanCast.hxx" #include #include @@ -72,7 +71,7 @@ ResourceLimits::IsEmpty() const noexcept inline std::size_t ResourceLimits::GetHash() const noexcept { - return djb_hash(ReferenceAsBytes(*this)); + return IntHashT(*this); } char * diff --git a/src/util/IntHash.hxx b/src/util/IntHash.hxx new file mode 100644 index 00000000..b42105f3 --- /dev/null +++ b/src/util/IntHash.hxx @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann + +#pragma once + +#include +#include +#include + +static constexpr std::size_t INT_HASH_INIT = 17; + +/** + * A very simple/naive and fast hash function for integers of + * arbitrary size. + */ +template +[[nodiscard]] [[gnu::always_inline]] [[gnu::hot]] +constexpr std::size_t +IntHashUpdate(T src, std::size_t hash) noexcept +{ + return (hash * 19) + static_cast(src); +} + +template +[[nodiscard]] [[gnu::hot]] +constexpr std::size_t +IntHash(std::span src, std::size_t hash=INT_HASH_INIT) noexcept +{ + for (const T i : src) + hash = IntHashUpdate(i, hash); + return hash; +} + +template +requires(std::has_unique_object_representations_v && sizeof(T) % sizeof(I) == 0 && alignof(T) % sizeof(I) == 0) +[[nodiscard]] [[gnu::hot]] +constexpr std::size_t +_IntHashT(const T &src, std::size_t hash=INT_HASH_INIT) noexcept +{ + constexpr std::size_t n = sizeof(src) / sizeof(I); + const std::span span{reinterpret_cast(&src), n}; + return IntHash(span, hash); +} + +/** + * Calculate the hash of an arbitrary (trivial) object, using the + * largest integer according to the object's alignment at compile + * time. + */ +template +requires std::has_unique_object_representations_v +[[nodiscard]] [[gnu::hot]] +constexpr std::size_t +IntHashT(const T &src, std::size_t hash=INT_HASH_INIT) noexcept +{ + if constexpr (sizeof(T) % 8 == 0) + return _IntHashT(src, hash); + else if constexpr (sizeof(T) % 4 == 0) + return _IntHashT(src, hash); + else if constexpr (sizeof(T) % 2 == 0) + return _IntHashT(src, hash); + else + return _IntHashT(src, hash); +}