搜尋
首頁後端開發php教程詳解PHP中被忽略的效能最佳化利器:生成器

詳解PHP中被忽略的效能最佳化利器:生成器

如果是做Python或是其他語言的小夥伴,對於生成器應該不陌生。但很多PHP開發者或許都不知道生成器這個功能,可能是因為生成器是PHP 5.5.0才引進的功能,也可以是生成器作用不是很明顯。但是,生成器功能的確非常有用。

優點

直接講概念估計你聽完還是一頭霧水,所以我們先來說說優點,也許能勾起你的興趣。那麼生成器有哪些優點,如下:

  • 生成器會對PHP應用的效能有非常大的影響
  • PHP程式碼運行時節省大量的記憶體
  • 比較適合計算大量的資料

那麼,這些神奇的功能究竟是如何做到的呢?我們先來舉個例子。

概念引入

首先,放下生成器概念的包袱,來看一個簡單的PHP函數:

function createRange($number){
    $data = [];
    for($i=0;$i<$number;$i++){
        $data[] = time();
    }
    return $data;
}复制代码

這是一個非常常見的PHP函數,我們在處理一些數組的時候常常會被使用。這裡的程式碼也非常簡單:

  1. 我們建立一個函數。
  2. 函數內包含一個for循環,我們循環的把目前時間放到$data裡面
  3. ##for#循環執行完畢,把$data返回出去。
下面沒完,我們繼續。我們再寫一個函數,把這個函數的回傳值循環印出來:

$result = createRange(10); // 这里调用上面我们创建的函数
foreach($result as $value){
    sleep(1);//这里停顿1秒,我们后续有用
    echo $value.&#39;<br />&#39;;
}复制代码

我們在瀏覽器裡面看一下運行結果:

![](https://picb.zhimg .com/80/v2-3620f3d46bb5b49e53ca47891ea1fd5a_720w.jpg)

這裡非常完美,沒有任何問題。 (當然

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.&#39;<br />&#39;;
}复制代码

![](https://pic2.zhimg.com/80/v2-9c08f2d01f7a68736f45ffa3d3934cc5_720w.jpg)

我們奇蹟般的發現了,輸出的值和第一次沒有使用生成器的不一樣。這裡的值(時間戳記)中間間隔了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.&#39;<br />&#39;;
}复制代码

我們來還原一下程式碼執行過程。

    首先呼叫
  1. createRange函數,傳入參數10,但是for值執行了一次然後停止了,並且告訴foreach第一次迴圈可以用的值。
  2. foreach開始對$result循環,進來首先sleep(1),然後開始使用for給的一個值執行輸出。
  3. foreach準備第二次循環,在開始第二次循環之前,它向#​​##for循環又請求了一次。
  4. for
  5. 循環於是又執行了一次,將生成的時間戳告訴foreach.
  6. foreach
  7. 拿到第二個值,並且輸出。由於foreachsleep(1),所以,for循環延遲了1秒生成目前時間##所以,整個程式碼執行中,總是只有一個記錄值參與循環,記憶體中只有一則資訊。
無論開始傳入的

$number

有多大,由於不會立即產生所有結果集,所以記憶體總是一條循環的值。

概念理解

到這裡,你應該已經大概理解什麼是生成器了。下面我們來說下生成器原理。

首先明确一个概念:生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值

那么代码中foreach循环的是什么?其实是PHP在使用生成器的时候,会返回一个Generator类的对象。foreach可以对该对象进行迭代,每一次迭代,PHP会通过Generator实例计算出下一次需要迭代的值。这样foreach就知道下一次需要迭代的值了。

而且,在运行中for循环执行后,会立即停止。等待foreach下次循环时候再次和for索要下次的值的时候,for循环才会再执行一次,然后立即再次停止。直到不满足条件不执行结束。

实际开发应用

很多PHP开发者不了解生成器,其实主要是不了解应用领域。那么,生成器在实际开发中有哪些应用?

读取超大文件

PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如5个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。

这里生成器就可以派上用场啦。简单看个例子:读取text文件

![](https://pic1.zhimg.com/80/v2-2d6fb1058b39008fbe4e5363e485e9a2_720w.jpg)

我们创建一个text文本文档,并在其中输入几行文字,示范读取。

<?php
header("content-type:text/html;charset=utf-8");
function readTxt()
{
    # code...
    $handle = fopen("./test.txt", &#39;rb&#39;);

    while (feof($handle)===false) {
        # code...
        yield fgets($handle);
    }

    fclose($handle);
}

foreach (readTxt() as $key => $value) {
    # code...
    echo $value.&#39;<br />&#39;;
}复制代码

![](https://pic4.zhimg.com/80/v2-2bbdc40ebf8f1aeedf2aa0c472811c77_720w.jpg)

通过上图的输出结果我们可以看出代码完全正常。

但是,背后的代码执行规则却一点儿也不一样。使用生成器读取文件,第一次读取了第一行,第二次读取了第二行,以此类推,每次被加载到内存中的文字只有一行,大大的减小了内存的使用。

这样,即使读取上G的文本也不用担心,完全可以像读取很小文件一样编写代码。

想了解更多编程学习,敬请关注php培训栏目!

以上是詳解PHP中被忽略的效能最佳化利器:生成器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:juejin。如有侵權,請聯絡admin@php.cn刪除
高流量網站的PHP性能調整高流量網站的PHP性能調整May 14, 2025 am 12:13 AM

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

PHP中的依賴注入:初學者的代碼示例PHP中的依賴注入:初學者的代碼示例May 14, 2025 am 12:08 AM

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

PHP性能:是否可以優化應用程序?PHP性能:是否可以優化應用程序?May 14, 2025 am 12:04 AM

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

PHP性能優化:最終指南PHP性能優化:最終指南May 14, 2025 am 12:02 AM

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

PHP依賴注入容器:快速啟動PHP依賴注入容器:快速啟動May 13, 2025 am 12:11 AM

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

PHP中的依賴注入與服務定位器PHP中的依賴注入與服務定位器May 13, 2025 am 12:10 AM

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

PHP性能優化策略。PHP性能優化策略。May 13, 2025 am 12:06 AM

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

PHP電子郵件驗證:確保正確發送電子郵件PHP電子郵件驗證:確保正確發送電子郵件May 13, 2025 am 12:06 AM

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

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

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

SublimeText3 英文版

SublimeText3 英文版

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

SecLists

SecLists

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

SublimeText3 Mac版

SublimeText3 Mac版

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

Safe Exam Browser

Safe Exam Browser

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