php – 优化基本转换循环

所以,对于我的密码学图书馆,我有一个经常使用的
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中的数字数组.因此,示例输入将是数组(1,1),2,10,其将给出数组(3)作为结果.另一个例子是数组(1,0,0),256,10,它们将给出数组(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次迭代).

有什么想法吗?

最佳答案 是的,可以稍微优化一下:

$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等代码优化器/编译器可以在这种情况下显着提高性能.

点赞