Avane 的速度慢了原生 require 的三十倍?

avane-logo

是時候該提到 Avane 的速度性能問題了,Avane 大概是在一年前出生的,

那個時候還沒想到「性能」的問題,只有想到關於編譯器(Avane 有自己的編譯器,看這裡暸解更多)

還有怎麼處理跟快取而已,但是最近發現就算 Avane 有快取,速度怎麼還是慢 PHP 原生的 Require 四分之一倍!?


實際測試

TeaMeow 取得模板必須透過 Avane,而當 TeaMeow 生成好幾個文章的時候,

必須不斷的重複執行 Avane

下面是用來測試 Avane 速度的程式代碼,執行 1000 次的讀取,然後取得花費的毫秒數。

//取得目前時間
$Time = microtime(true);

//執行 1000 次的 Avane 讀取模板
for($i=0; $i<1000; $i++)
    $Avane->Load('tpl/test-build', false, ['TestVariable' => '1234567']);

//取得完成時間
$Done = microtime(true) - $Time;

//重設目前時間
$Time = microtime(true);

//執行 1000 次的原生 Require
for($i=0; $i<1000; $i++)
    require('tpl/test-build.t.php');

//取得完成時間
$Done2 = microtime(true) - $Time;

//輸出兩者時間
exit(var_dump([$Done, $Done2]));

初次結果

螢幕快照 2015-07-23 下午6.52.35

看起來不是很好的結果,Avane 花了 1.733 秒,而原生則花了 0.056 秒而已,

實際上差了三十倍左右。


改善快取時間檢查!

Avane 本身有快取系統,原理就是在編譯器編譯時,會先查看快取,然後檢查快取有沒有過期,

下面是 Avane 在這段執行的代碼

if(file_exists($SavePath))
    /** The cache is not expired */
    if(time() - filemtime($SavePath) > $ExpireTime)
        return $ReturnTpl(file_get_contents($SavePath), $SavePath);
    else
        return false;
else
    return false;

那麼先來處理快取的問題吧,讓我先把檢查快取時間的那段註釋掉,看看會怎麼樣:

if(file_exists($SavePath))
    /** The cache is not expired */
    //if(time() - filemtime($SavePath) > $ExpireTime)
        return ReturnTpl(file_get_contents($SavePath), $SavePath);
    //else
    //    return false;
else
    return false;

時間馬上從 1.733 秒變成 0.293 秒啦!

原來 filemtime() 這麼吃效能嗎 .. 那就暫時先讓 Avane 忽略時間檢查吧。


改善讀取時間!

接下來該改善的應該是 file_get_contents(),聽說這個函數沒有內建快取,

導致每次取得檔案,都要重新讀取一遍,現在,先幫我們的 Avane 增加一個「快取桶子」吧。

//如果這個沒有被丟進快取桶子的話
if(!isset($CacheBucket[$SavePath]))
{
    //那麼我們就讀取檔案,然後把內容丟進「快取桶子」
    $CacheBucket[$SavePath] = file_get_contents($SavePath);
}

現在花費的時間則是 0.147 秒了,看起來速度更快了,現在只慢原生的 0.056 秒大概兩倍


改善類別速度!

Avane 分為四個部分左右,基本上就是 JSSCSS編譯器領銜主演(?)

每當要 $Avane->Load() 的時候,都必須詢問編譯器,編譯器去查詢快取,然後返回快取

那麼現在,直接略過編譯器呢?(那我上面快取桶子是做假的嗎幹)

其實我在寫這篇文章的時候嘗試把快取桶子砍掉,我發現有快取桶子還是比較快欸wwww

理念

所以像我說的,我們必須詢問編譯器,那麼現在我這樣做:

第一次跟編譯器要求結果,編譯器會返回快取的位置,我們直接把快取的位置在丟到「快取桶子二」(?)

第二次,我們就直接在從「快取桶子二」中拿位置,就無視編譯器了。

我他媽一定天才。

實作

//如果快取桶子二中,有我們現在要的模板
if(isset($CacherBucket[$TplPath]))
{
    //儲存變數到 Avane 引擎,所以快取模板可以用
    Set($Variables);
    //直接讀取快取桶子二中的路徑
    require($CacherBucket[$TplPath]);
}
else
{
    //告訴編譯器並讀取檔案,然後儲存已編譯的位置
    $CacherBucket[$TplPath] = Parser($TplPath, $AsContent, $Variables)['Path'];
    //直接讀取快取桶子二中的路徑
    require($CacherBucket[$TplPath]);
}

最終結果

所以我找了其他模板來測試,最終結果則是:

螢幕快照 2015-07-26 下午10.02.34

沒錯,Avane 花費 0.031 秒,而原生 Require 則花了 0.037 秒啊!


「愛衣ちゃん大勝利ぃー!!!!!」

Avane 終於比原生 Require 快了,我有故事可以告訴我未來的小孩了(?)

總結: Avane 現在快原生 Require 0.8 倍。

對「Avane 的速度慢了原生 require 的三十倍?」的想法

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s