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

标签 php mysql performance recursion memory-management

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

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

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

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

非常简单的函数 - 如果是数字,则转换成 double ,如果是数组或对象,则递归地进行。

这里一切就绪。

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

  1. 如何改进此功能? (速度,内存)
  2. 为什么要花这么长时间?即使是 json_encode,我认为它是一个更大的函数,花费的时间要少得多。

最佳答案

因为强制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(实现字符串到 double 转换的第三种方法)甚至更长,所以没有比使用 PHP 做得更好的了。您要实现的是脚本操作,不应将其用作 Web 应用程序的正常后端操作。

但如果您仍然想这样做,您可以提高 php.ini 文件中的 memory_limitas long as you don't use the -1 workaround .

更新

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

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

=> 34.018 毫秒。

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

=> 17.081 毫秒。

并且显然使用通过引用 进行强制转换会得到更好的结果:

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

=> 13.1 毫秒。

关于PHP - 将字符串递归替换为数字需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37908562/

相关文章:

mysql - 在过滤的 GROUP BY 查询上优化 MySQL ORDER BY RAND() 以避免临时/无索引连接

javascript - 如何阻止连接提前关闭?

php - 设置服务器

sql - 优化对大表的最近行的查询性能

php - 如何使用 fgetcsv 删除空白行

MySql 子查询和 max 或 group by?

java - 什么时候并行执行任务是一种矫枉过正的行为?

php - 需要面向对象设计的建议 : a collection of items

php - 如何使用 PHP 更改 XML 标记名称?

javascript - AJAX 和 php 脚本后添加的表单元素未传输到 $_POST