所以,对于我的密码学图书馆,我经常使用base converter。它不是世界上最有效的东西,但它适用于所有输入范围。
大部分工作由回调循环完成:
$callback = function($source, $src, $dst) {
$div = array();
$remainder = 0;
foreach ($source as $n) {
$e = floor(($n + $remainder * $src) / $dst);
$remainder = ($n + $remainder * $src) % $dst;
if ($div || $e) {
$div[] = $e;
}
}
return array(
$div,
$remainder
);
};
while ($source) {
list ($source, $remainder) = $callback($source, $srcBase, $dstBase);
$result[] = $remainder;
}
基本上,它需要$srcBase
中的一组数字,并将它们转换为$dstBase
中的数字数组。因此,示例输入为array(1, 1), 2, 10
,结果会给出array(3)
。另一个例子是array(1, 0, 0), 256, 10
,它会给array(1, 6, 7, 7, 7, 2, 1, 6)
(数组的每个元素都是$dstBase
中的一个“数字”。
我现在面临的问题是,如果我提供2kb的数据,则需要将近10秒的时间才能运行。所以我开始优化它。到目前为止,通过使用此递归循环替换整个结构,我将其缩短到大约4秒:
while ($source) {
$div = array();
$remainder = 0;
foreach ($source as $n) {
$dividend = $n + $remainder * $srcBase;
$res = (int) ($dividend / $dstBase);
$remainder = $dividend % $dstBase;
if ($div || $res) {
$div[] = $res;
}
}
$result[] = $remainder;
$source = $div;
}
我面临的问题是如何进一步优化(如果可能的话)。我认为问题是大输入所需的剪切迭代次数(对于2000元素数组,从基数256到基数10,总共需要4,815,076次迭代)。
有什么想法吗?
答案 0 :(得分:2)
执行此脚本所用时间的99.9%源于迭代输入的固有需求。由于foreach中的代码非常基本,因此减少执行时间的唯一方法是减少迭代次数。如果那是不可能的,那么你就拥有了这个功能最有效的版本。
答案 1 :(得分:1)
是的,它可以稍微优化一下:
$source_count = count($source);
while ($source) {
$remainder = $i = 0;
foreach ($source AS &$n) {
$dividend = $n + $remainder * $srcBase;
$remainder = $dividend % $dstBase;
$res = ($dividend - $remainder) / $dstBase;
if ($i || $res)
$source[$i++] = $res;
}
for ($j=$i; $j < $source_count; $j++)
unset($source[$i]);
$source_count=$i;
$result[] = $remainder;
}
甚至更快,但更加模糊:
$source_count = count($source);
while ($source) {
$remainder = $i = 0;
foreach ($source AS &$n) {
if (($res = ($dividend - ($remainder = ($dividend = $n + $remainder * $srcBase) % $dstBase)) / $dstBase) || $i)
$source[$i++] = $res;
}
for ($j=$i; $j < $source_count; $j++)
unset($source[$i]);
$source_count=$i;
$result[] = $remainder;
}
你将获得一些内存和CPU使用量减少,但它更有趣但是cource不可读(:。
但我个人认为你这样做是错误的。我认为你应该使用一些快速的C代码来完成这种任务(通过使用系统调用或编写/安装现有的PHP模块)。我认为像Hip-Hop PHP,Zend Optimized等代码优化器/编译器可以在这种情况下显着提高性能。
答案 2 :(得分:-1)
我不确定,但是
$dividend = $remainder * $srcBase + $n;
可能会快一点......