Как создать 64-битный хэш Murmur v2 в PHP 7.2?

У меня есть база данных MySQL, в которой есть некоторые хэши Murmur2 (64-разрядные целые числа без знака), которые были сгенерированы с помощью Percona UDF, которая поставляется вместе с веткой Percona базы данных MySQL, найденной здесь. https://github.com/percona/build-test/blob/master/plugin/percona-udf/murmur_udf.cc

Моя проблема в том, что теперь мне нужно сгенерировать те же самые хеши на стороне PHP, но я не могу найти или настроить что-либо существующее, чтобы работать / выводить один и тот же вывод для того же ввода.

Вещи, которые я пробовал:

  1. Копирование функции C ++ из Percona UDF в мою разветвленную версию этого расширения PHP, которое первоначально создавало 32-битные int-хэши https://github.com/StirlingMarketingGroup/php_murmurhash. Это почти сработало, как в скомпилированном, но когда я выполняю функцию в PHP, сервер apache падает с segfault, и я недостаточно знаком с расширениями C ++ и PHP, чтобы отладить это

Segfault вызвано тем, что я запустил эту функцию

var_dump(murmurhash('Hello World'));

Который нормально работает, когда я скачал https://github.com/kibae/php_murmurhash (оригинал, 32 бита, расширение, создающее хэш) и следовал инструкциям, но как только я заменил функцию (редактируйте только в файле MurmurHash2.cpp, чтобы https://github.com/StirlingMarketingGroup/php_murmurhash/blob/master/MurmurHash2.cpp) тот же вызов функции приводит к сбою PHP-скрипта.

  1. Попытка перенести функцию Percona UDF C ++ на PHP. Я не уверен, что моя функция PHP на 100% точна при попытке учесть приращение указателя, но я подозреваю, что причина, по которой я получаю совершенно другой вывод в версии PHP, связана с тем, что PHP не поддерживает целые числа без знака.

Вот функция PHP, которую я написал как порт из функции Percona C ++

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.

Есть ли что-то, что можно исправить с помощью любого из моих двух предыдущих подходов, или, возможно, уже работающий подход, который я могу использовать вместо этого?

0

Решение

Я решил это сам, по сути, портировав хеш-функцию 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 не поддерживает целые числа без знака.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]