http://blog.roga.tw/2011/07/php-%E4%BD%BF%E7%94%A8-apc-%E5%A2%9E%E9%80%B2%E5%9F%B7%E8%A1%8C%E9%80%9F%E5%BA%A6%E3%80%82/
其實,如果單純講速度的話,其實 PHP 還真的不夠快,但為什麼其它語言會快呢?其實原因很多,但其實都不脫以下幾項:
1. 程式事先編譯好,而不是要用的時候才用 Interpreter 直譯出結果。
2. 東西能放記憶體的就放記憶體
3. 主機的硬體夠力(這個因素佔很大)
PHP 也有非常多方式可以幫自己加速,這邊我要推薦的是 APC 這個 PHP Extension。
安裝方法大家都會,甚至有些架站包都預設幫你裝好了,所以這邊就不贅述。這邊要提的是 APC 有許多參數可以設置,彈性很大,尤其有個對於加速至關緊要的參數:apc.stat=0
如果你覺得自己的 PHP 網站不快,可以在自己的 php.ini 裡面,load 進來 apc.so 後面加上 apc.stat=0 ,對樣對網站的效能會有顯著地提昇。原理是因為 APC 在每次讀取 PHP 程式碼的時候,都會先 stat() 程式碼所在的檔案,以確定要不要重新編譯成 OPCODE ,而 apc.stat=0 則是直接省略 stat() 的步驟,拿原本就有的 opcode 來用。
而當使用了 APC 並且設置 apc.stat=0 之後,其實網站在第一次編譯成 OPCODE 之後,除非重起或是清除快取,要不然就是會一直拿 OPCODE 來跑,而這樣速度也因此有了顯著的提升。
假設有一段程式碼如下:
02 | include_once ( '/www/includes/1.inc' ); |
03 | include_once ( '/www/includes/2.inc' ); |
04 | include_once ( '/www/includes/3.inc' ); |
05 | include_once ( '/www/includes/4.inc' ); |
06 | include_once ( '/www/includes/5.inc' ); |
07 | include_once ( '/www/includes/6.inc' ); |
08 | include_once ( '/www/includes/7.inc' ); |
09 | include_once ( '/www/includes/8.inc' ); |
10 | include_once ( '/www/includes/9.inc' ); |
11 | include_once ( '/www/includes/10.inc' ); |
則在背後 APC 的動作會像是上面這張圖一樣,可以看得出來 apc.stat=0 時,省了非常多的 stat() 。
這樣的優點是速度會變快,但小缺點是當程式有更動的時候,要 FLUSH OPCODE CACHE 才能看到程式修改後的結果(FLUSH OPCODE CACHE 的方式可以用 APC 內建的 Function 或是重新啟動 Web Server)。我在自己筆電上面灌好 MAMP ,把加速器換成 APC 然後 /Applications/MAMP/conf/php5.3/php.ini 裡面只加入一行設定:apc.stat=0 。印 Hello World 跑出來結果如下:
ab -c 10 -t 1 -k http://127.0.0.1/index.php
roga@Hephaestus:/Applications/MAMP/conf/php5.3$ ab -c 10 -t 1 -k http://127.0.0.1/index.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Finished 15598 requests
Server Software: Apache/2.0.64
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /index.php
Document Length: 11 bytes
Concurrency Level: 10
Time taken for tests: 1.000 seconds
Complete requests: 15598
Failed requests: 0
Write errors: 0
Keep-Alive requests: 15448
Total transferred: 3721178 bytes
HTML transferred: 171578 bytes
Requests per second: 15597.49 [#/sec] (mean)
Time per request: 0.641 [ms] (mean)
Time per request: 0.064 [ms] (mean, across all concurrent requests)
Transfer rate: 3633.84 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 0 1 0.2 1 4
Waiting: 0 1 0.2 1 4
Total: 0 1 0.2 1 5
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 1
95% 1
98% 1
99% 1
100% 5 (longest request)
每秒大概處理 15597.49 個 request 。所以如果只印 Hello World 的話,其實 PHP 也不差
不過我也得說明一下,我的 MBP 是 15″ 的 Intel Core i7 2.2GHz, 8GB RAM, 120GB SSD (哈,這樣算作弊嗎?) 另外,在我的 MBP 上,如果連線不 keep alive 的話,速度會降到 5793.44 req/sec ,但這是 tcp connection 和 apache 產生的 overhead ,就不要怪到 PHP 的速度上了。最後,有篇 Facebook 的 Slide 在講 APC 的細部調整,對 performance tuning 有興趣的,不妨一讀:PHP Tek 2008 : APC @ Facebook 。