2016-06-19 28 views
3

因为MySQL的“选择”,选择整形和浮点字符串,我需要每一个反应,我得到(从JS)是在一个正确的数据模型 -PHP - 递归到位替换字符串到数字的时间太长

  • 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的内存..

  1. 如何改进此功能? (速度,内存)
  2. 为什么需要这么长时间?甚至json_encode,我会认为这是一个更大的功能花费更少的时间..
+0

你尝试类型杂耍,而不是:'$混合[$关键] = 0 + $ VAL;'? –

+0

@IvanGabriele还没有。我不明白它对速度有何帮助?当然,内存大部分时间都是4个字节而不是8个。我正在尝试 – Amit

+0

您的问题还有另一种解决方案。这是在服务器上更新mysqlnd所以PHP得到正确的数据类型从MySQL ...... [这里的详细说明](http://stackoverflow.com/questions/1197005/how-to-get-numeric-types-from-mysql-使用-PDO) –

回答

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应用程序的常规后端操作。

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

UPDATE

我忘了一个可能的优化,你应该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毫秒。

+0

这些是非常好的比较!但它可能是在PHP7 ..我忘了提及,我使用5.5.34(不能升级),这里是一个例子:http://sandbox.onlinephpfunctions.com/code/5b261993efbc969cfd7c4df9f03a1b5bb0d6b460 - 它需要0.35秒和看起来很优化..它看起来像它并不需要太多的内存,现在这是伟大 – Amit

+0

@Amit这正是一个比我发现13.1毫秒同样的功能......反正它也不会提高其链接你的内存问题事实上你的原始数据量太大了。你仍然必须提高你的'memory_limit'。你应该[阅读](http://stackoverflow.com/a/7993775/2736233)了解PHP内存分配是如何工作的。 –

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功能实现更大的改善。

+0

虽然这有效,但它并没有改变很多的执行时间。此外,阵列的步行递归不能处理对象 – Amit

+0

这就是为什么我没有提供array_walk_recursive溶液;它实际上部分可以, 如果你的对象实现了'ArrayAccess'它可以; – godvsdeity