目錄
優點
概念引入
思考一個問題
建立生成器
使用生成器
深入理解生成器
程式碼剖析
概念理解
实际开发应用
读取超大文件
首頁 後端開發 php教程 PHP中被忽略的效能最佳化利器:生成器

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

Dec 08, 2017 pm 01:58 PM
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 />';
}
登入後複製

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

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

這裡非常完美,沒有任何問題。 (當然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 />';
}
登入後複製

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

#我們奇蹟般的發現了,輸出的值和第一次沒有使用生成器的不一樣。這裡的值(時間戳記)中間間隔了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 />';
}
登入後複製

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

  1. 先呼叫createRange函數,傳入參數10,但for值執行了一次然後停止了,並且告訴foreach第一次迴圈可以用的值。

  2. foreach開始對$result循環,進來首先sleep(1),然後開始使用 for給的一個值執行輸出。

  3. foreach準備第二次循環,開始第二次循環之前,它向#​​##for循環又請求了一次。

  4. for循環於是又執行了一次,將產生的時間戳記告訴foreach.

  5. foreach拿到第二個值,並且輸出。由於foreachsleep(1),所以,for循環延遲了1秒產生目前時間

  6. ##所以,整個程式碼執行中,總是只有一個記錄值參與循環,記憶體中也只有一則訊息。

无论开始传入的$number有多大,由于并不会立即生成所有结果集,所以内存始终是一条循环的值。

概念理解

到这里,你应该已经大概理解什么是生成器了。下面我们来说下生成器原理。

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

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

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

实际开发应用

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

读取超大文件

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

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

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

我们创建一个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.'<br />';
}
登入後複製

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

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

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

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

相关推荐:

php性能优化:isset()比strlen()更快

最全的php服务器性能优化配置方案

5个php7性能优化技巧总结

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

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

討論 CakePHP 討論 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的開源框架。它旨在使應用程式的開發、部署和維護變得更加容易。 CakePHP 基於類似 MVC 的架構,功能強大且易於掌握。模型、視圖和控制器 gu

CakePHP 檔案上傳 CakePHP 檔案上傳 Sep 10, 2024 pm 05:27 PM

為了進行文件上傳,我們將使用表單助理。這是文件上傳的範例。

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

CakePHP 快速指南 CakePHP 快速指南 Sep 10, 2024 pm 05:27 PM

CakePHP 是一個開源MVC 框架。它使應用程式的開發、部署和維護變得更加容易。 CakePHP 有許多函式庫可以減少大多數常見任務的過載。

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

See all articles