是時候該提到 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]));
初次結果
看起來不是很好的結果,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 分為四個部分左右,基本上就是 JS、SCSS、編譯器、領銜主演(?)
每當要 $Avane->Load() 的時候,都必須詢問編譯器,編譯器去查詢快取,然後返回快取,
那麼現在,直接略過編譯器呢?(那我上面快取桶子是做假的嗎幹)
其實我在寫這篇文章的時候嘗試把快取桶子砍掉,我發現有快取桶子還是比較快欸wwww
理念
所以像我說的,我們必須詢問編譯器,那麼現在我這樣做:
第一次跟編譯器要求結果,編譯器會返回快取的位置,我們直接把快取的位置在丟到「快取桶子二」(?)
第二次,我們就直接在從「快取桶子二」中拿位置,就無視編譯器了。
我他媽一定天才。
實作
//如果快取桶子二中,有我們現在要的模板 if(isset($CacherBucket[$TplPath])) { //儲存變數到 Avane 引擎,所以快取模板可以用 Set($Variables); //直接讀取快取桶子二中的路徑 require($CacherBucket[$TplPath]); } else { //告訴編譯器並讀取檔案,然後儲存已編譯的位置 $CacherBucket[$TplPath] = Parser($TplPath, $AsContent, $Variables)['Path']; //直接讀取快取桶子二中的路徑 require($CacherBucket[$TplPath]); }
最終結果
所以我找了其他模板來測試,最終結果則是:
沒錯,Avane 花費 0.031 秒,而原生 Require 則花了 0.037 秒啊!
「愛衣ちゃん大勝利ぃー!!!!!」
Avane 終於比原生 Require 快了,我有故事可以告訴我未來的小孩了(?)
如果把 Avane 底層用 C++ 寫,接著用 PHP 調用C++ API,這樣會不會比較快? _(:3 」∠ )_
讚讚
好像很好玩
讚讚
[…] 這次的亞凡芽也帶有了上次的快取桶子,之後可能會另外命名就是了。 […]
讚讚