我如何优化这个循环以在PHP上快速运行。在javascript上运行非常快
因此,我一直在将一些代码从Javascript移植到PHP,现在可以工作了,但是,执行时间非常差。在PHP中大约需要26秒,而在javascript中速度非常快。我已经能够将其分解为导致问题的for循环。这是循环我如何优化这个循环以在PHP上快速运行。在javascript上运行非常快,javascript,php,loops,for-loop,Javascript,Php,Loops,For Loop,因此,我一直在将一些代码从Javascript移植到PHP,现在可以工作了,但是,执行时间非常差。在PHP中大约需要26秒,而在javascript中速度非常快。我已经能够将其分解为导致问题的for循环。这是循环 for ($R0d = 0; $R0d < $F0d; $R0d = $R0d + 16) { $f0d = [bitwise_and(JS_charCodeAt($C0d,($R0d + 4)), 0xff) | shift_left_32((b
for ($R0d = 0; $R0d < $F0d; $R0d = $R0d + 16) {
$f0d = [bitwise_and(JS_charCodeAt($C0d,($R0d + 4)), 0xff) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 5)), 0xff)), 8) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 6)), 255)), 16) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 7)), 255)), 24), bitwise_and(JS_charCodeAt($C0d, ($R0d)), 255) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 1)), 255)), 8) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 2)), 255)), 16) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 3)), 0xff)), 24)];
$H0d = [bitwise_and(JS_charCodeAt($C0d, ($R0d + 12)), 255) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 13)), 255)), 8) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 14)), 255)), 16) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 15)), 255)), 24), bitwise_and(JS_charCodeAt($C0d, ($R0d + 8)), 255) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 9)), 255)), 8) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 10)), 255)), 16) | shift_left_32((bitwise_and(JS_charCodeAt($C0d, ($R0d + 11)), 255)), 24)];
$f0d = x64Multiply($f0d, $M0d);
$f0d = x64Rotl($f0d, 31);
$f0d = x64Multiply($f0d, $I0d);
$P0d = x64Xor($P0d, $f0d);
$P0d = x64Rotl($P0d, 27);
$P0d = x64Add($P0d, $o0d);
$P0d = x64Add(x64Multiply($P0d, [0, 5]), [0, 1390208809]);
$H0d = x64Multiply($H0d, $I0d);
$H0d = x64Rotl($H0d, 33);
$H0d = x64Multiply($H0d, $M0d);
$o0d = x64Xor($o0d, $H0d);
$o0d = x64Rotl($o0d, 31);
$o0d = x64Add($o0d, $P0d);
$o0d = x64Add(x64Multiply($o0d, [0, 5]), [0, 944331445]);
}
我正在使用此篮球图像的base64代码测试此哈希的实现:
哈希包含字符串的开头,包括mime类型
所以这将导致存储的值为:data:image/jpeg;base64,[base64编码字符串]
我从这个网站上得到了base64数据
然后,我将该值存储在名为
$testValue
的变量中,并运行以下函数调用$output=x64hash128($testValue,31)代码>导致值c5aed78543b2b31c233fa4289e0eadfa您的主要问题是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);
}
函数JS_charCodeAt($str,$index){
静态$utf16s=[];
如果(isset($utf16s[$str]))
$utf16=$utf16s[$str];
其他的
$utf16s[$str]=$utf16=mb_convert_编码($str,'UTF-16LE','UTF-8');
返回ORD太长了,读不下去了(OutF16[$index 2)+(ORD($utf16[$index 2 ++] 1)tl;如果这是MurmurHash,那么去看看。
否则,您可以摆脱大量不必要的函数调用,如下所示:
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.
($i=0;$i<$F0d;$i+=16)的{
//让我们从这个块开始。它做什么?它显然需要一个8字节的块
//一次四个,并构建一对32位字。
//每个字节都使用0xFF按位和按位进行编码,以确保其为8位值。
$f0d=[
按位_和(JS_charCodeAt($C0d,($i+4)),0xff)
|左移位32((按位)和(JS_charCodeAt($C0d,($i+5)),0xff)),8)
|左移位32((按位移位)和(按位移位($C0d,($i+6)),255)),16)
|左移位32((按位移位)和(按位移位($C0d,($i+7)),255)),24),
按位_和(JS_charCodeAt($C0d,($i)),255)
|左移位32((按位移位)和(按位移位($C0d,($i+1)),255)),8)
|左移位32((按位移位)和(按位移位($C0d,($i+2)),255)),16)
|左移位32((按位移位)和(按位移位($C0d,($i+3)),0xff)),24),
];
//我们可以在PHP中使用unpack()函数并在$C0d的适当substr()上键入V来执行相同的操作。
//但是由于unpack()的变幻莫测和元素颠倒的事实,
//我们不能单独使用unpack(好吧,我们可以,如果我们改变下面的算法,但是这太尴尬了)。
$x0d=array_reverse(数组_值(unpack('V2',substr($C0d,$i,8)));
//如果现在转储$f0d和$x0d,它们应该是相同的。
//您可以使用$H0d执行同样的操作。
//实际上,您可以同时执行这两项操作,避免数组操作,但我没有检查(只需执行一个简单的测试运行,并将$x0d的内容与$f0d和$H0d的内容进行比较):
$x0d=unpack('V4',substr($C0d,$i,16));
$f0d=[$x0d[2],$x0d[1];
$H0d=[$x0d[4],$x0d[3];
//并将所有16个字节整齐地转换为两个32位字数组。
你能给我整个文件吗,这样我就可以运行它并为你进行优化了?我不认为这个问题只是你发送到这里的一部分。但我关注的是PHP性能,所以我打赌我可以大大降低它。函数调用很昂贵,使用本机数据类型和算术运算符。无论如何,可能只是内联函数和使用本机操作相反,它们中的大多数都能做到这一点。这种节奏中的函数调用非常昂贵。这同样适用于[0,5]行中的数组构造等等,您至少应该将其扩展到属性,或者直接内联。好的,一旦我回到联机状态,很快就会发布更多代码。我使用函数调用的唯一原因是,我需要值为32位,就像复制我想要的相同输出所需的Javascript一样。这些函数确保整数值为32位,而不是64位PHP一直在做什么。我知道,但你可以通过在计算后添加&0xFFFFFFFF来实现。不需要函数。原因是,JS速度快得多可能是因为浏览器有智能优化器和JIT,它们为你内联并转换为本机代码。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.