PHP - 递归到位将字符串替换为数字需要太长时间

时间:2016-06-19 14:58:27

标签: php mysql performance recursion memory-management

因为MYSQL的“SELECT”选择整数和浮点数作为字符串,我需要每个响应(从JS)获得正确的数据模型 -

  • 1不是“1”,
  • 53.2不是“53.2”,

我创建了这个递归函数,适用于混合类型 - 数组/对象:

import psutil
for proc in psutil.process_iter():
       print proc.open_files()

非常简单的函数 - 如果是数字,则转换为double,如果是数组或对象,则重复执行。

这里的一切都已到位。

我有两个问题:   - 在6MB的数据上,大多数数字表示为字符串,花费0.5秒   - 在200MB的数据上(是的,我需要它,请不要专注于它),它在几分钟(通常是几秒钟)后失败,说它需要超过4GB的内存..

  1. 如何改进此功能? (速度,记忆)
  2. 为什么需要这么久?甚至json_encode,我认为是一个更大的功能需要更少的时间..

2 个答案:

答案 0 :(得分:2)

因为强制used to be faster than casting,我运行此代码来计算PHP 7上的时序:

function getTime($start) {
    return round((microtime(true) - $start) * 1000000) / 1000;
}

function mockData($length) {
    $data = [];
    $i = -1;

    while ($i++ < $length) {
        $data[$i] = strval(rand(1, 10000) / 100);
    }

    return $data;
}

$data = mockData(100000);

// Let's check that they are string before
echo gettype($data[0]) . '<br><br>';

$start = microtime(true);
$convertedData = [];
foreach ($data as $key => $value) {
    $convertedData[$key] = (double) $value;
}
echo '(double) cast took ' . getTime($start) . ' ms.<br>';

$start = microtime(true);
$convertedData = [];
foreach ($data as $key => $value) {
    $convertedData[$key] = 0 + $value;
}
echo 'Coercion took ' . getTime($start) . ' ms.<br>';

我的结果是:

(double) cast took 27.508 ms.
Coercion took 28.789 ms.

<强>结论

由于使用floatval(实现字符串到双重转换的第三种方式)甚至更长,因此使用PHP无法做得更好。您尝试实现的是脚本操作,它不应该用作Web应用程序的正常后端操作。

但如果您仍想这样做,可以在memory_limit文件as long as you don't use the -1 workaround内更高php.ini

<强>更新

我忘了一个可能的优化,你应该pass your variable by reference至少执行立即分配:

$start = microtime(true);
foreach ($data as $key => $value) {
    $data[$key] = (double) $value;
}
echo getTime($start) . ' ms.<br>';

<强> =&GT; 34.018毫秒。

$start = microtime(true);
foreach ($data as &$value) {
    $value = (double) $value;
}
echo getTime($start) . ' ms.<br>';

<强> =&GT; 17.081毫秒。

显然,通过参考使用进行强制可以获得更好的效果:

$start = microtime(true);
foreach ($data as &$value) {
    $value = 0 + $value;
}
echo getTime($start) . ' ms.<br>';

<强> =&GT; 13.1 ms。

答案 1 :(得分:1)

这应该会提高速度和记忆力:

private function cast_number(&$mixed)
{
    foreach ($mixed as &$val) {
        if (is_numeric($val)) {
            $val = (double) $val;
        } else if (is_array($val) || is_object($val)) {
            $this->cast_number($val);
        }
    }
    // do not return $mixed
}

但也许您可以使用array_walk_recursive函数获得更大的改进。