如何在 PHP 7.2 中生成 64 位 Murmur 哈希 v2?
How to generate a 64bit Murmur hash v2 in PHP 7.2?
我有一个 MySQL 数据库,其中包含一些 Murmur2 哈希值(作为无符号 64 位整数),这些哈希值是使用 MySQL 数据库的 Percona 链附带的 Percona UDF 生成的 MySQL https://github.com/percona/build-test/blob/master/plugin/percona-udf/murmur_udf.cc
我的问题是现在我需要在 PHP 端生成这些相同的散列,但我似乎无法找到或调整 work/output 相同输出的任何现有内容输入。
我尝试过的事情:
- 将 C++ 函数从 Percona UDF 复制到我的这个 PHP 扩展的分叉版本中,该扩展最初生成 32 位 int 哈希 https://github.com/StirlingMarketingGroup/php_murmurhash。这几乎是有效的,因为它已编译,但是当我在 PHP 中执行该函数时,apache 服务器因段错误而崩溃,我对 C++ 和 PHP 扩展不够熟悉,无法调试此
段错误是我造成的运行这个函数
var_dump(murmurhash('Hello World'));
当我下载 https://github.com/kibae/php_murmurhash (the original, 32bit, hash producing extension) and followed the instructions, but once I replaced the function (Only edit in the MurmurHash2.cpp file to https://github.com/StirlingMarketingGroup/php_murmurhash/blob/master/MurmurHash2.cpp 时它正常工作)相同的函数调用使 PHP 脚本崩溃。
- 正在尝试将 Percona UDF C++ 函数移植到 PHP。我不太确定我的 PHP 函数在尝试解释指针递增时是否 100% 准确,但我怀疑更多,所以我得到与 PHP 版本完全不同的输出的原因有一些原因使用 PHP 不支持无符号整数。
这是我作为 Percona C++ 函数
的端口编写的 PHP 函数
function murmurhash2(string $s) : int {
$len = strlen($s);
$seed = 0;
$m = 0x5bd1e995;
$r = 24;
$h1 = $seed ^ $len;
$h2 = 0;
$i = 0;
while ($len >= 8) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
$k2 = ord($s[$i++]);
$k2 *= $m; $k2 ^= $k2 >> $r; $k2 *= $m;
$h2 *= $m; $h2 ^= $k2;
$len -= 4;
}
if ($len >= 4) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
}
switch ($len) {
case 3: $h2 ^= ord($s[2]) << 16;
case 2: $h2 ^= ord($s[1]) << 8;
case 1: $h2 ^= ord($s[0]);
$h2 *= $m;
};
$h1 ^= $h2 >> 18; $h1 *= $m;
$h2 ^= $h1 >> 22; $h2 *= $m;
$h1 ^= $h2 >> 17; $h1 *= $m;
$h = $h1;
$h = ($h << 32) | $h2;
return $h;
}
在 MySQL 我明白了
select murmur_hash('Hello World'), cast(murmur_hash('Hello World')as unsigned), CONV(cast(murmur_hash('Hello World')as unsigned), 10, 16);
-- -8846466548632298438 9600277525077253178 853B098B6B655C3A
然后 PHP 我得到
var_dump(murmurhash2('Hello World'));
// int(5969224437940092928)
因此查看 MySQL 和 PHP 结果,有符号和无符号都不匹配我的 PHP 输出。
是否可以使用我之前的两种方法中的任何一种来解决某些问题,或者我可以改用一种已经有效的方法?
我通过将 Percona 散列函数直接移植到 PHP 扩展 MySQL 上,自己解决了这个问题。
安装和使用说明张贴在这里https://github.com/StirlingMarketingGroup/php-murmur-hash
示例输出
在 MySQL 中,Percona 扩展的用法类似于
select`murmur_hash`('Yeet')
-- -7850704420789372250
并在 PHP
php -r 'echo murmur_hash("Yeet");'
// -7850704420789372250
请注意,对于这两种环境,这些都被视为有符号整数,您可以在 MySQL 中使用 cast(`murmur_hash`('Yeet')as unsigned)
解决这个问题,但 PHP 不支持无符号整数。
我有一个 MySQL 数据库,其中包含一些 Murmur2 哈希值(作为无符号 64 位整数),这些哈希值是使用 MySQL 数据库的 Percona 链附带的 Percona UDF 生成的 MySQL https://github.com/percona/build-test/blob/master/plugin/percona-udf/murmur_udf.cc
我的问题是现在我需要在 PHP 端生成这些相同的散列,但我似乎无法找到或调整 work/output 相同输出的任何现有内容输入。
我尝试过的事情:
- 将 C++ 函数从 Percona UDF 复制到我的这个 PHP 扩展的分叉版本中,该扩展最初生成 32 位 int 哈希 https://github.com/StirlingMarketingGroup/php_murmurhash。这几乎是有效的,因为它已编译,但是当我在 PHP 中执行该函数时,apache 服务器因段错误而崩溃,我对 C++ 和 PHP 扩展不够熟悉,无法调试此
段错误是我造成的运行这个函数
var_dump(murmurhash('Hello World'));
当我下载 https://github.com/kibae/php_murmurhash (the original, 32bit, hash producing extension) and followed the instructions, but once I replaced the function (Only edit in the MurmurHash2.cpp file to https://github.com/StirlingMarketingGroup/php_murmurhash/blob/master/MurmurHash2.cpp 时它正常工作)相同的函数调用使 PHP 脚本崩溃。
- 正在尝试将 Percona UDF C++ 函数移植到 PHP。我不太确定我的 PHP 函数在尝试解释指针递增时是否 100% 准确,但我怀疑更多,所以我得到与 PHP 版本完全不同的输出的原因有一些原因使用 PHP 不支持无符号整数。
这是我作为 Percona C++ 函数
的端口编写的 PHP 函数function murmurhash2(string $s) : int {
$len = strlen($s);
$seed = 0;
$m = 0x5bd1e995;
$r = 24;
$h1 = $seed ^ $len;
$h2 = 0;
$i = 0;
while ($len >= 8) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
$k2 = ord($s[$i++]);
$k2 *= $m; $k2 ^= $k2 >> $r; $k2 *= $m;
$h2 *= $m; $h2 ^= $k2;
$len -= 4;
}
if ($len >= 4) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
}
switch ($len) {
case 3: $h2 ^= ord($s[2]) << 16;
case 2: $h2 ^= ord($s[1]) << 8;
case 1: $h2 ^= ord($s[0]);
$h2 *= $m;
};
$h1 ^= $h2 >> 18; $h1 *= $m;
$h2 ^= $h1 >> 22; $h2 *= $m;
$h1 ^= $h2 >> 17; $h1 *= $m;
$h = $h1;
$h = ($h << 32) | $h2;
return $h;
}
在 MySQL 我明白了
select murmur_hash('Hello World'), cast(murmur_hash('Hello World')as unsigned), CONV(cast(murmur_hash('Hello World')as unsigned), 10, 16);
-- -8846466548632298438 9600277525077253178 853B098B6B655C3A
然后 PHP 我得到
var_dump(murmurhash2('Hello World'));
// int(5969224437940092928)
因此查看 MySQL 和 PHP 结果,有符号和无符号都不匹配我的 PHP 输出。
是否可以使用我之前的两种方法中的任何一种来解决某些问题,或者我可以改用一种已经有效的方法?
我通过将 Percona 散列函数直接移植到 PHP 扩展 MySQL 上,自己解决了这个问题。
安装和使用说明张贴在这里https://github.com/StirlingMarketingGroup/php-murmur-hash
示例输出
在 MySQL 中,Percona 扩展的用法类似于
select`murmur_hash`('Yeet')
-- -7850704420789372250
并在 PHP
php -r 'echo murmur_hash("Yeet");'
// -7850704420789372250
请注意,对于这两种环境,这些都被视为有符号整数,您可以在 MySQL 中使用 cast(`murmur_hash`('Yeet')as unsigned)
解决这个问题,但 PHP 不支持无符号整数。