summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-05-08 16:43:54 +0300
committerDmitry Stogov <dmitry@zend.com>2019-05-08 16:47:12 +0300
commit90e285f6fda679c18259e459c8585ebf284805b0 (patch)
tree913317e3f1ec5b0a649b7d6500846273ca6bc7e8
parentee0fc1b5ae9470e7edd43b608d43a8bea93188d2 (diff)
downloadphp-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.h44
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