PHP-以递归方式将字符串替换为数字花费的时间太长 [英] PHP - Recursive in place replacing of strings to numbers takes too long
问题描述
因为MYSQL的"SELECT"选择整数并将其作为字符串进行浮点运算,所以我需要从JS中获得的每个响应都必须位于正确的数据模型中-
Because MYSQL's "SELECT" selects integers and floats as strings, and I need every response I get (from JS) to be in a correct data model -
- 1个不是"1",
- 53.2不是"53.2",
我创建了适用于混合类型-数组/对象的递归函数:
I created this recursive function that works on mixed type - array/object:
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;
}
非常简单的功能-如果为数字,则转换为双精度,如果为数组或对象,则递归遍历.
Pretty simple function - if is number, cast double, if is array or object, go over recursivly.
这里的一切都准备就绪.
Everything here is in place.
我对此有两个问题: -在6MB的数据上,大多数数字以字符串表示,耗时0.5秒 -在200MB的数据上(是的,我需要它,请不要专注于它),它在几分钟(通常是几秒钟)后失败,表示需要4GB以上的内存.
I have two problems with this: - On 6MB of data, of mostly numbers that are represented as strings it took 0.5 seconds - On 200MB of data (yes, I need it, please don't focus on it), it failed after a couple of minutes (usually seconds), saying it needs more than 4GB of memory..
- 如何改善此功能? (速度,内存)
- 为什么要花这么长时间?甚至json_encode,我认为这是一个更大的函数也需要更少的时间..
推荐答案
由于强制以前比强制转换快,我运行了这段代码来计算PHP 7上的计时:
Because coercion used to be faster than casting, I ran this code to calculate timings on 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应用程序的常规后端操作.
Since using floatval
(a third way to achieve string to double conversion) is even longer, you can't do better than that with PHP. What you're trying to achieve is a scripting operation, it shouldn't be used as a normal back-end operation for a web application.
但是,如果您仍然希望这样做,则可以在php.ini
文件不要使用-1
解决方法.
But if you still want to do that, you can higher your memory_limit
inside your php.ini
file, as long as you don't use the -1
workaround.
更新
我忘记了一种可能的优化方法,您应该通过引用传递变量至少执行立即分配:
I forgot one possible optimization, you should pass your variable by reference to at least execute immediate assignation :
$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毫秒.
显然,通过引用使用强制将产生更好的结果:
And apparently using coercion with by reference gives even better results :
$start = microtime(true);
foreach ($data as &$value) {
$value = 0 + $value;
}
echo getTime($start) . ' ms.<br>';
=> 13.1毫秒.
这篇关于PHP-以递归方式将字符串替换为数字花费的时间太长的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!