diff options
author | Dmitry Stogov <dmitry@zend.com> | 2019-05-08 16:43:54 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2019-05-08 16:47:12 +0300 |
commit | 90e285f6fda679c18259e459c8585ebf284805b0 (patch) | |
tree | 913317e3f1ec5b0a649b7d6500846273ca6bc7e8 | |
parent | ee0fc1b5ae9470e7edd43b608d43a8bea93188d2 (diff) | |
download | php-git-90e285f6fda679c18259e459c8585ebf284805b0.tar.gz |
Improve PHP hash function.
See Daniel Lemire's blog post https://lemire.me/blog/2016/07/21/accelerating-php-hashing-by-unoptimizing-it/
-rw-r--r-- | Zend/zend_string.h | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 4ede3f0381..793a519ce2 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -361,6 +361,49 @@ static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size { zend_ulong hash = Z_UL(5381); +#if defined(_WIN32) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) + /* Version with multiplication works better on modern CPU */ + for (; len >= 8; len -= 8, str += 8) { + hash = + hash * 33 * 33 * 33 * 33 + + str[0] * 33 * 33 * 33 + + str[1] * 33 * 33 + + str[2] * 33 + + str[3]; + hash = + hash * 33 * 33 * 33 * 33 + + str[4] * 33 * 33 * 33 + + str[5] * 33 * 33 + + str[6] * 33 + + str[7]; + } + if (len >= 4) { + hash = + hash * 33 * 33 * 33 * 33 + + str[0] * 33 * 33 * 33 + + str[1] * 33 * 33 + + str[2] * 33 + + str[3]; + len -= 4; + str += 4; + } + if (len >= 2) { + if (len > 2) { + hash = + hash * 33 * 33 * 33 + + str[0] * 33 * 33 + + str[1] * 33 + + str[2]; + } else { + hash = + hash * 33 * 33 + + str[0] * 33 + + str[1]; + } + } else if (len != 0) { + hash = hash * 33 + *str; + } +#else /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { hash = ((hash << 5) + hash) + *str++; @@ -383,6 +426,7 @@ static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size case 0: break; EMPTY_SWITCH_DEFAULT_CASE() } +#endif /* Hash value can't be zero, so we always set the high bit */ #if SIZEOF_ZEND_LONG == 8 |