因为mysql的“select”选择整数和浮点数作为字符串,我需要(从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;
}
非常简单的函数-如果是数字,强制双精度,如果是数组或对象,递归遍历。
这里的一切都准备好了。
我有两个问题:
-在6MB的数据中,大多数数字是用字符串表示的,它花费了0.5秒
-对于200MB的数据(是的,我需要它,请不要关注它),它在几分钟(通常是几秒钟)后失败,说它需要超过4GB的内存。
如何改进此功能?(速度,内存)
为什么要花这么长时间?即使是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
(实现字符串到双精度转换的第三种方法)的时间甚至更长,因此使用php做不到比这更好的事情。您要实现的是一个脚本操作,它不应该用作web应用程序的常规后端操作。但如果你还想这么做,你可以在
memory_limit
文件中提高php.ini
,as 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毫秒。