如果是做Python或是其他語言的小夥伴,對於生成器應該不陌生。但很多PHP開發者或許都不知道生成器這個功能,可能是因為生成器是PHP 5.5.0才引進的功能,也可以是生成器作用不是很明顯。但是,生成器功能的確非常有用。
優點
直接講概念估計你聽完還是一頭霧水,所以我們先來說說優點,也許能勾起你的興趣。那麼生成器有哪些優點,如下:
- 生成器會對PHP應用的效能有非常大的影響
- PHP程式碼運行時節省大量的記憶體
- 比較適合計算大量的資料
那麼,這些神奇的功能究竟是如何做到的呢?我們先來舉個例子。
概念引入
首先,放下生成器概念的包袱,來看一個簡單的PHP函數:
function createRange($number){ $data = []; for($i=0;$i<$number;$i++){ $data[] = time(); } return $data; }复制代码
這是一個非常常見的PHP函數,我們在處理一些數組的時候常常會被使用。這裡的程式碼也非常簡單:
- 我們建立一個函數。
- 函數內包含一個
for
循環,我們循環的把目前時間放到$data
裡面 - ##for
#循環執行完畢,把
$data返回出去。
$result = createRange(10); // 这里调用上面我们创建的函数 foreach($result as $value){ sleep(1);//这里停顿1秒,我们后续有用 echo $value.'<br />'; }复制代码我們在瀏覽器裡面看一下運行結果:這裡非常完美,沒有任何問題。 (當然
sleep(1)效果你們看不出來)
createRange的時候給
$number的傳值是10,一個很小的數字。假設,現在傳遞一個值
10000000(1000萬)。
createRange裡面,
for循環就需要執行
1000萬次。且有
1000萬個值被放到
$data裡面,而
$data陣列在是被放在記憶體內。所以,在呼叫函數時候會佔用大量記憶體。
function createRange($number){ for($i=0;$i<$number;$i++){ yield time(); } }复制代码看下這段和剛剛很像的程式碼,我們刪除了陣列
$ data,而且也沒有回傳任何內容,而是在
time()之前使用了一個關鍵字
yield
$result = createRange(10); // 这里调用上面我们创建的函数 foreach($result as $value){ sleep(1); echo $value.'<br />'; }复制代码我們奇蹟般的發現了,輸出的值和第一次沒有使用生成器的不一樣。這裡的值(時間戳記)中間間隔了1秒。 這裡的間隔一秒其實就是
sleep(1)造成的後果。但為什麼第一次沒有間隔呢?那是因為:
- 未使用生成器時:
- createRange
函數內的
for循環結果很快就會放到
$data中,並且立即返回。所以,
foreach循環的是一個固定的陣列。
使用生成器時: - createRange
的值不是一次快速生成,而是依賴
foreach循環。
foreach迴圈一次,
for執行一次。
function createRange($number){ for($i=0;$i<$number;$i++){ yield time(); } } $result = createRange(10); // 这里调用上面我们创建的函数 foreach($result as $value){ sleep(1); echo $value.'<br />'; }复制代码我們來還原一下程式碼執行過程。
- 首先呼叫
- createRange
函數,傳入參數
10,但是
for值執行了一次然後停止了,並且告訴
foreach第一次迴圈可以用的值。
- foreach
開始對
$result循環,進來首先
sleep(1),然後開始使用
for給的一個值執行輸出。
- foreach
準備第二次循環,在開始第二次循環之前,它向###for
循環又請求了一次。 for - 循環於是又執行了一次,將生成的時間戳告訴
foreach
. foreach - 拿到第二個值,並且輸出。由於
foreach
中sleep(1)
,所以,for
循環延遲了1秒生成目前時間##所以,整個程式碼執行中,總是只有一個記錄值參與循環,記憶體中只有一則資訊。
$number
有多大,由於不會立即產生所有結果集,所以記憶體總是一條循環的值。概念理解
首先明确一个概念:生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值
那么代码中foreach
循环的是什么?其实是PHP在使用生成器的时候,会返回一个Generator
类的对象。foreach
可以对该对象进行迭代,每一次迭代,PHP会通过Generator
实例计算出下一次需要迭代的值。这样foreach
就知道下一次需要迭代的值了。
而且,在运行中for
循环执行后,会立即停止。等待foreach
下次循环时候再次和for
索要下次的值的时候,for
循环才会再执行一次,然后立即再次停止。直到不满足条件不执行结束。
实际开发应用
很多PHP开发者不了解生成器,其实主要是不了解应用领域。那么,生成器在实际开发中有哪些应用?
读取超大文件
PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如5个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。
这里生成器就可以派上用场啦。简单看个例子:读取text文件

我们创建一个text文本文档,并在其中输入几行文字,示范读取。
<?php header("content-type:text/html;charset=utf-8"); function readTxt() { # code... $handle = fopen("./test.txt", 'rb'); while (feof($handle)===false) { # code... yield fgets($handle); } fclose($handle); } foreach (readTxt() as $key => $value) { # code... echo $value.'<br />'; }复制代码

通过上图的输出结果我们可以看出代码完全正常。
但是,背后的代码执行规则却一点儿也不一样。使用生成器读取文件,第一次读取了第一行,第二次读取了第二行,以此类推,每次被加载到内存中的文字只有一行,大大的减小了内存的使用。
这样,即使读取上G的文本也不用担心,完全可以像读取很小文件一样编写代码。
想了解更多编程学习,敬请关注php培训栏目!
以上是詳解PHP中被忽略的效能最佳化利器:生成器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

TheSecretTokeEpingAphp-PowerEdwebSiterUnningSmoothlyShyunderHeavyLoadInVolvOLVOLVOLDEVERSALKEYSTRATICES:1)emplactopCodeCachingWithOpcachingWithOpCacheToreCescriptexecution Time,2)使用atabasequercachingCachingCachingWithRedataBasEndataBaseLeSendataBaseLoad,3)

你應該關心DependencyInjection(DI),因為它能讓你的代碼更清晰、更易維護。 1)DI通過解耦類,使其更模塊化,2)提高了測試的便捷性和代碼的靈活性,3)使用DI容器可以管理複雜的依賴關係,但要注意性能影響和循環依賴問題,4)最佳實踐是依賴於抽象接口,實現鬆散耦合。

是的,優化papplicationispossibleandessential.1)empartcachingingcachingusedapcutorediucedsatabaseload.2)優化的atabaseswithexing,高效Quereteries,and ConconnectionPooling.3)EnhanceCodeWithBuilt-unctions,避免使用,避免使用ingglobalalairaiables,並避免使用

theKeyStrategiestosigantificallyBoostPhpaPplicationPerformenCeare:1)UseOpCodeCachingLikeLikeLikeLikeLikeCacheToreDuceExecutiontime,2)優化AtabaseInteractionswithPreparedStateTementStatementStatementAndProperIndexing,3)配置

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增強codemodocultion,可驗證性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

選擇DependencyInjection(DI)用於大型應用,ServiceLocator適合小型項目或原型。 1)DI通過構造函數注入依賴,提高代碼的測試性和模塊化。 2)ServiceLocator通過中心註冊獲取服務,方便但可能導致代碼耦合度增加。

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)啟用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替換loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

phpemailvalidation invoLvesthreesteps:1)格式化進行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。