2016-06-19 60 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