在 PHP 中使用 `yield` 來作內存優化

你有沒有想過 "在 PHP 中使用 yield 會有什麼益處",我將爲你節省一些谷歌搜索的時間; 我列出了一些要向你介紹的要點來全面認知 yieldjavascript

  1. 什麼是 yield
  2. yield & return 的區別。
  3. yield 有什麼選項。
  4. 結論。
  5. 參考。

1. 什麼是 "yield"

生成器函數看上去就像一個普通函數, 除了不是返回一個值以外, 生成器會根據需求產生更多的值。php

來看如下的例子:java

function getValues() { yield 'value'; } // 輸出字符串 "value" echo getValues(); 

固然, 這不是他生效的方式, 前面的例子會給你一個致命的錯誤: 類生成器的對象不能被轉換成字符串, 讓咱們清楚的說明:laravel

2. "yield" & "return" 的區別

前面的錯誤意味着 getValues() 方法不會如預期返回一個字符串,讓咱們檢查一下他的類型:數組

function getValues() { return 'value'; } var_dump(getValues()); // string(5) "value" function getValues() { yield 'value'; } var_dump(getValues()); // class Generator#1 (0) {} 

生成器 類實現了 生成器 接口, 這意味着你必須遍歷 getValue() 方法來取值:服務器

foreach (getValues() as $value) { echo $value; } // 使用變量也是好的 $values = getValues(); foreach ($values as $value) { echo $value; } 

但這不是惟一的不一樣!函數

一個生成器運行你寫使用循環來迭代一維數組的代碼,而不須要在內存中建立是一個數組,這可能會致使你超出內存限制。性能

在下面的例子裏咱們建立一個有 800,000 元素的數字同時從 getValues() 方法中返回他,同時在此期間,咱們將使用函數 memory_get_usage() 來獲取分配給次腳本的內存, 咱們將會每增長 200,000 個元素來獲取一下內存使用量,這意味着咱們將會提出四個檢查點:spa

<?php function getValues() { $valuesArray = []; // 獲取初始內存使用量 echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL; for ($i = 1; $i < 800000; $i++) { $valuesArray[] = $i; // 爲了讓咱們能進行分析,因此咱們測量一下內存使用量 if (($i % 200000) == 0) { // 來 MB 爲單位獲取內存使用量 echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL; } } return $valuesArray; } $myValues = getValues(); // 一旦咱們調用函數將會在這裏建立數組 foreach ($myValues as $value) {} 

前面例子發生的狀況是這個腳本的內存消耗和輸出:.net

0.34 MB
8.35 MB
16.35 MB
32.35 MB

這意味着咱們的幾行腳本消耗了超過 30 MB 的內存, 每次你你添加一個元素到 $valuesArray 數組中, 都會增長他在內存中的大小。

讓咱們使用 yield 一樣的例子:

<?php function getValues() { // 獲取內存使用數據 echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL; for ($i = 1; $i < 800000; $i++) { yield $i; // 作性能分析,所以可測量內存使用率 if (($i % 200000) == 0) { // 內存使用以 MB 爲單位 echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL; } } } $myValues = getValues(); // 在循環以前都不會有動做 foreach ($myValues as $value) {} // 開始生成數據 

這個腳本的輸出使人驚訝:

0.34 MB
0.34 MB
0.34 MB
0.34 MB

這不意味着你從 return 表達式遷移到 yield,但若是你在應用中建立會致使服務器上內存出問題的巨大數組,則 yield 更加適合你的狀況。


3. 什麼是 "yield" 選項

這裏有不少 yield 的選項, 我將強調他們中的幾個:

a. 使用 yield, 你也可使用 return

function getValues() { yield 'value'; return 'returnValue'; } $values = getValues(); foreach ($values as $value) {} echo $values->getReturn(); // 'returnValue' 

b. 返回鍵值對:

function getValues() { yield 'key' => 'value'; } $values = getValues(); foreach ($values as $key => $value) { echo $key . ' => ' . $value; } 

點擊 這裏 查看更多。

4. 結論

這個主題的主要緣由是爲了明確 yieldreturn 特別是在內存使用方面的區別,使用一些例子是由於我發現他對任何開發人員思考真的很重要。

5. 參考

  1. http://php.net/manual/en/language.generators.syntax.php
  2. http://php.net/manual/en/class.generator.php
  3. http://php.net/manual/en/language.generators.php
  4. http://php.net/manual/en/function.memory-get-usage.php

討論請前往:https://laravel-china.org/topics/8704

做者:summerbluet 連接:https://www.jianshu.com/p/103cbf359971
相關文章
相關標籤/搜索