2 回答
TA贡献1817条经验 获得超6个赞
如果这是 MurmurHash,那么去看看https://github.com/lastguest/murmurhash-php。
否则,您可以摆脱大量不必要的函数调用,如下所示:
for ($i = 0; $i < $F0d; $i += 16) {
// Let's start with this block. What does it do? It clearly takes a block of 8 bytes
// four at a time, and builds a pair of 32-bit words.
// Each byte is AND-ed bitwise with 0xFF to ensure it is a 8-bit value.
$f0d = [
bitwise_and(JS_charCodeAt($C0d, ($i + 4)), 0xff)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 5)), 0xff)), 8)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 6)), 255)), 16)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 7)), 255)), 24),
bitwise_and(JS_charCodeAt($C0d, ($i)), 255)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 1)), 255)), 8)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 2)), 255)), 16)
| shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($i + 3)), 0xff)), 24),
];
// We can do the same thing in PHP using the unpack() function and type V on an appropriate substr() of $C0d.
// But due to the vagaries of unpack() and the fact that the elements are reversed,
// we cannot use unpack alone (well, we COULD, if we changed the algorithm below, but it would be too awkward).
$x0d = array_reverse(array_values(unpack('V2', substr($C0d, $i, 8))));
// If you now dump $f0d and $x0d, they should be identical.
// You can do the same with $H0d.
// Actually you can do both together, avoiding the array manipulation, BUT I HAVEN'T CHECKED (just do a simple test run and verify $x0d's contents comparing it to $f0d and $H0d's):
$x0d = unpack('V4', substr($C0d, $i, 16));
$f0d = [ $x0d[2], $x0d[1] ];
$H0d = [ $x0d[4], $x0d[3] ];
// and get all 16 bytes neatly converted in two two-32-bit word arrays.
TA贡献2016条经验 获得超9个赞
您的主要问题在于错误编写的 JS_charCodeAt 函数。通过增加输入大小,性能呈指数级下降,因为每次调用单个字符时,此函数都会从 UTF8 - UTF16 转换整个输入。
添加这个简单的缓存将工作时间减少了 100 倍。只需替换此功能:
function JS_charCodeAt($str, $index) {
static $utf16s = [];
if (isset($utf16s[$str]))
$utf16 = $utf16s[$str];
else
$utf16s[$str] = $utf16 = mb_convert_encoding($str, 'UTF-16LE', 'UTF-8');
return ord($utf16[$index*2]) + (ord($utf16[$index*2+1]) << 8);
}
当然,有很多事情是错误的,但这是非常容易和快速修复的,并且会产生最大的不同。到目前为止,如果您需要更高的性能,我可以进一步研究它。但该代码真的应该完全重写,这是一团糟。但现在它至少有效。
- 2 回答
- 0 关注
- 228 浏览
添加回答
举报