黑夜路人同学的php论坛

05月 3, 2008 on 12:08 pm | In 未分类 | 1 Comment

地址是:http://www.phpcup.cn/
对PHP我基本没什么更高的追求,看上去php似乎已经无以复加,在web领域没有什么不能干的了。
但是对小亮同学组织人开个php论坛支持新手的行为,还是表示支持。赞一个。
我在这儿做了基础版版主,我这水平也就能糊弄糊弄新手:(
欢迎大拿们去评点评点…

用fastCGI协议进行RPC调用

12月 6, 2007 on 8:57 pm | In php性能, php技术 | 2 Comments

近来由于业务量急剧增长,业务种类越来越多,RPC混乱问题就凸现出来.
具体表现是:
a1,a2,a3,a4 为一组服务器,为用户提供A服务.
b1,b2,b3为一组服务器,为用户提供B服务.
c1,c2,c3为一组服务器,为用户提供C服务.
最初各服务器各自服务是不太相关的.随着业务拓展,用户提出新的需求,我们需要
在A服务中调用B组服务器的API接口.
….
最后我们发现这样一个现象:
用户请求a1 提供服务.a1发现他需要知道另一些数据,于是调用b2的rpc服务.但是b2
上这个数据又需要c3的RPC.结果c3又需要a2来提供一些数据….
我们的远程调用调来调去,最后把自己调晕了.

于是我开始考虑一种解决方案。
首先当然是:对远程调用加以控制和规范,避免不必要的远程调用。
接着我注意到,我们利用CURL来通过http通道进行远程调用其实是没必要的。我可以在做远程调用时,走FastCGI协议。

说干就干:
第一步:建立一个fastCGI:spawn-php

  1. #!/bin/bash
  2.  
  3. ## ABSOLUTE path to the spawn-fcgi binary
  4. SPAWNFCGI="/home/y/opt/lighttpd/bin/spawn-fcgi"
  5.  
  6. ## ABSOLUTE path to the PHP binary
  7. FCGIPROGRAM="/home/y/opt/php/bin/php-cgi"
  8.  
  9. ## TCP port to which to bind on localhost
  10. FCGIPORT="1026"
  11.  
  12. ## number of PHP children to spawn
  13. PHP_FCGI_CHILDREN=10
  14.  
  15. ## maximum number of requests a single PHP process can serve before it is restarted
  16. PHP_FCGI_MAX_REQUESTS=1000
  17.  
  18. ## IP addresses from which PHP should access server connections
  19. FCGI_WEB_SERVER_ADDRS="127.0.0.1,192.168.2.10"
  20.  
  21. # allowed environment variables, separated by spaces
  22. ALLOWED_ENV="ORACLE_HOME PATH USER"
  23.  
  24. ## if this script is run as root, switch to the following user
  25. USERID=y
  26. GROUPID=y
  27.  
  28. ################## no config below this line
  29.  
  30. if test x$PHP_FCGI_CHILDREN = x; then
  31. PHP_FCGI_CHILDREN=5
  32. fi
  33.  
  34. export PHP_FCGI_MAX_REQUESTS
  35. export FCGI_WEB_SERVER_ADDRS
  36.  
  37. ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
  38.  
  39. if test x$UID = x0; then
  40. EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
  41. else
  42. EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
  43. fi
  44.  
  45. # copy the allowed environment variables
  46. E=
  47.  
  48. for i in $ALLOWED_ENV; do
  49. E="$E $i=${!i}"
  50. done
  51.  
  52. # clean the environment and set up a new one
  53. env - $E $EX

2.接着我们建立这样的文件:http.txt

  1. for($i=0;$i<100;$i++)
  2. {
  3. echo rand();
  4. echo '....Scene of shooting at Nebraska shopping centre
  5. Eight killed in Nebraska shooting
  6. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  7. Scene of shooting at Nebraska shopping centre
  8. Eight killed in Nebraska shooting
  9. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  10. Scene of shooting at Nebraska shopping centre
  11. Eight killed in Nebraska shooting
  12. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  13. Scene of shooting at Nebraska shopping centre
  14. Eight killed in Nebraska shooting
  15. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  16. ';
  17. }
  18. print "done!";

这个做为是远程接口。
3.下面比较CURL和fastCGI两种访问remote API的方式:
A:走FastCGI:

  1. include "./mod_fcgi.php";
  2. $fcgi=new mod_fcgi();
  3. $args="127.0.0.1:1026";
  4. $filename="/home/y/www/qps/http.php";
  5. $fcgi->parser_open($args,$filename,$rq_err,$cgi_headers);
  6. print($fcgi->parsed_output);
  7. echo "\n=============\n";

B:走CURL通道:

  1. include "./curl.php";
  2. $curl=& new CURL();
  3. echo $curl->get("http://localhost/qps/http.php");
  4. echo "\n=============\n";

4我们比较FCGI方式和CURL方式的差异:
FCGI方式进行远程调用的QPS:

  1. Total transferred:      249306 bytes
  2. HTML transferred:       244410 bytes
  3. Requests per second:    275.77 [#/sec] (mean)
  4. Time per request:       3.626 [ms] (mean)
  5. Time per request:       3.626 [ms] (mean, across all concurrent requests)
  6. Transfer rate:          2233.76 [Kbytes/sec] received

HTTP通道进行远程调用的QPS:

  1. Total transferred:      2244515 bytes
  2. HTML transferred:       2240015 bytes
  3. Requests per second:    204.18 [#/sec] (mean)
  4. Time per request:       4.898 [ms] (mean)
  5. Time per request:       4.898 [ms] (mean, across all concurrent requests)
  6. Transfer rate:          14911.66 [Kbytes/sec] received

经过多次比较,确认用fastCGI通道时,效率比http方式要高。
但是….这个差别并不大,而且,使用lighttpd的spawn-cgi来充当fastcgi的守护进程,还不是特别稳定。
另外,经过我的测试,只有当远程调用的结果有较多的输出时,FastCGI协议与HTTP协议相比才有优势。在通过网络传输的数据不多的情况下(就是http.php几乎没有输出的情况下),用CURL来调远端调用,反而比FastCGI方式慢(显而易见,mod_fcgi是自行封装的用PHP的socket函数来进行网络操作的class,而Curl是一个编译了的php扩展).
因此,我忙活了半天,最后得出的结论是,目前还不能在公司大规模加以运用。
但是对于小型企业,创业型公司来说,这种效率对比还是很有用的,可以加以挖掘。

为什么SELECT col1,col2,col3,col4 会比SELECT * 慢?

10月 7, 2007 on 1:31 pm | In 未分类 | 5 Comments

之前做过一个测试:
select id,title from ** 与select * from **的速度测试。
这是后续版.

  1. <?php
  2. define("TIMES",10000);
  3. $SQL1="SELECT * FROM stat_visits";
  4. $SQL2="SELECT v_id,v_url,v_site_id,v_screen_size,v_h,v_m,v_s,v_flash,v_director,
  5. v_quicktime,v_realplayer,v_pdf,v_windowsmedia,v_java,v_cookie,v_ref,v_remote_ip,
  6. v_timezone,v_color_depth,v_type,v_year,v_month,v_day,v_time FROM stat_visits";
  7. $conn=mysql_connect("localhost","root","");
  8. mysql_select_db("test");
  9. $time1=array_sum(explode(' ', microtime()));
  10. for($i=0;$i<times;$i++)
  11. </times;$i++)
  12.   mysql_query($SQL1);
  13. $time2=array_sum(explode(' ', microtime()));
  14. for($i=0;$i<times;$i++)
  15. </times;$i++)
  16.   mysql_query($SQL2);
  17. $time3=array_sum(explode(' ', microtime()));
  18.  
  19. $cost1=$time2-$time1;
  20. $cost2=$time3-$time2;
  21. print "cost1:$cost1\n";
  22. print "cost2:$cost2\n";
  23.  
  24. ?>

测试的结果是:

  1. [st@localhost test]$ php select.php
  2. cost1:2.1355810165405
  3. cost2:2.5820469856262
  4. [st@localhost test]$ php select.php
  5. cost1:1.9796178340912
  6. cost2:2.5190000534058
  7. [st@localhost test]$ php select.php
  8. cost1:1.9672379493713
  9. cost2:2.9030020236969
  10. [st@localhost test]$ php select.php
  11. cost1:1.9810240268707
  12. cost2:2.5505940914154

好了,现在将SQL1和SQL2次序交换:

  1. calhost test]$ php select.php
  2. cost1:2.5933158397675
  3. cost2:2.0362050533295
  4. [st@localhost test]$ php select.php
  5. cost1:2.6104090213776
  6. cost2:2.056037902832
  7. [st@localhost test]$ php select.php
  8. cost1:4.2802629470825
  9. cost2:3.3958988189697
  10. [st@localhost test]$ php select.php
  11. cost1:2.6283531188965
  12. cost2:2.0102050304413

大体上,SELECT COL1,COL2,COL3….. 与SELECT * 相比,两者花费的时间之比是4:5.不知道非空表的结果会不会是这样?

用ab来做性能测评好像不公平吧?

08月 21, 2007 on 11:47 pm | In php性能, php技术 | 1 Comment

我的师兄,从某种程度上说也是我php方面的师父,和他的同事做了测评,分别是针对php4,php5的性能对比和function,class的性能对比的。
这里是师兄的对比结果
师兄的同事做的测评
但是我不认为用ab来做出的测试是合理的.理由:用ab来测试时,结果好像总似是在跳舞一样.做为证据,我将我的notebook依文本方式重启,用ab来测lighttpd的表现.
具体环境:
Haier H40S Notebook
RAM:1.5G
CPU:CY 1.6GHz
硬盘:60G,(具体型号什么的不清楚,列个60G表示不是SCSI硬盘)
OS:Fedora Core 7.0(Moonshine)
web server:lighttpd 1.4.15
测试工具:ab
X环境:未运行X server
命令:ab -n 10000 -c 50 http://localhost:8181/
第一份结果:

  1. This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
  2. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  3. Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Server Software: lighttpd/1.4.15
Server Hostname: localhost
Server Port: 8181

Document Path: /
Document Length: 345 bytes

Concurrency Level: 50
Time taken for tests: 1.786830 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10000
Total transferred: 4980000 bytes
HTML transferred: 3450000 bytes
Requests per second: 5596.50 [#/sec] (mean)
Time per request: 8.934 [ms] (mean)
Time per request: 0.179 [ms] (mean, across all concurrent requests)
Transfer rate: 2721.58 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 2.6 4 8
Processing: 1 4 0.7 5 6
Waiting: 0 1 1.7 2 5
Total: 5 8 2.2 8 13
WARNING: The median and mean for the processing time are not within a normal deviation
These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
50% 8
66% 10
75% 10
80% 11
90% 11
95% 12
98% 12
99% 12
100% 13 (longest request)

这里的结果是Requests per second: 5596.50 [#/sec] (mean)(插一句,lighttpd的性能真是好,用apache从来没上过3000)
第二份ab -n 10000 -c 50的结果:

  1. This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
  2. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  3. Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Server Software: lighttpd/1.4.15
Server Hostname: localhost
Server Port: 8181

Document Path: /
Document Length: 345 bytes

Concurrency Level: 50
Time taken for tests: 1.313719 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10011
Total transferred: 4985478 bytes
HTML transferred: 3453795 bytes
Requests per second: 7611.98 [#/sec] (mean)
Time per request: 6.569 [ms] (mean)
Time per request: 0.131 [ms] (mean, across all concurrent requests)
Transfer rate: 3705.51 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.0 1 5
Processing: 1 5 2.0 5 32
Waiting: 0 3 1.8 3 30
Total: 1 6 2.1 6 35

Percentage of the requests served within a certain time (ms)
50% 6
66% 6
75% 6
80% 6
90% 7
95% 8
98% 10
99% 11
100% 35 (longest request)

结果表明RPS是Requests per second: 7611.98 [#/sec] (mean).
第三份结果:

  1. This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
  2. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  3. Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Server Software: lighttpd/1.4.15
Server Hostname: localhost
Server Port: 8181

Document Path: /
Document Length: 345 bytes

Concurrency Level: 50
Time taken for tests: 1.300247 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10009
Total transferred: 4984482 bytes
HTML transferred: 3453105 bytes
Requests per second: 7690.85 [#/sec] (mean)
Time per request: 6.501 [ms] (mean)
Time per request: 0.130 [ms] (mean, across all concurrent requests)
Transfer rate: 3743.14 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.0 1 5
Processing: 1 4 1.4 5 11
Waiting: 0 2 1.1 3 8
Total: 1 6 1.2 6 14

Percentage of the requests served within a certain time (ms)
50% 6
66% 6
75% 6
80% 6
90% 7
95% 9
98% 10
99% 11
100% 14 (longest request)

RPS结果是Requests per second: 7690.85 [#/sec] (mean).
第四份结果是:

  1. This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
  2. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  3. Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Server Software: lighttpd/1.4.15
Server Hostname: localhost
Server Port: 8181

Document Path: /
Document Length: 345 bytes

Concurrency Level: 50
Time taken for tests: 1.315784 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10033
Total transferred: 4996434 bytes
HTML transferred: 3461385 bytes
Requests per second: 7600.03 [#/sec] (mean)
Time per request: 6.579 [ms] (mean)
Time per request: 0.132 [ms] (mean, across all concurrent requests)
Transfer rate: 3708.06 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.2 1 8
Processing: 1 4 1.4 5 11
Waiting: 0 2 1.1 3 8
Total: 1 6 1.4 6 15

Percentage of the requests served within a certain time (ms)
50% 6
66% 6
75% 6
80% 6
90% 7
95% 9
98% 11
99% 12
100% 15 (longest request)

结果是Requests per second: 7600.03 [#/sec] (mean).
第五份结果是:

  1. This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
  2. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  3. Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)

Server Software: lighttpd/1.4.15
Server Hostname: localhost
Server Port: 8181

Document Path: /
Document Length: 345 bytes

Concurrency Level: 50
Time taken for tests: 1.812989 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10000
Total transferred: 4980000 bytes
HTML transferred: 3450000 bytes
Requests per second: 5515.75 [#/sec] (mean)
Time per request: 9.065 [ms] (mean)
Time per request: 0.181 [ms] (mean, across all concurrent requests)
Transfer rate: 2682.31 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 2.7 4 9
Processing: 1 4 0.8 5 6
Waiting: 0 1 1.7 2 5
Total: 5 8 2.3 9 13
WARNING: The median and mean for the processing time are not within a normal deviation
These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
50% 9
66% 10
75% 10
80% 11
90% 12
95% 12
98% 12
99% 12
100% 13 (longest request)

RPS结果是Requests per second: 5515.75 [#/sec] (mean);

可以看到,同是ab -n 10000 -c 50 http://localhost:8181/,结果大不一样,不仅分为7600RPS和5500RPS两档,而各档中具体数据也不一样.这个结果可以理解,OS中总是会有各种各样的消息要处理,影响具体数据结果也很正常.
因此,谢华亮(sir?mm?)的测试用ab的结果来进行php4,php5的性能比较是不太对的.至少目前看来,我没有从他的文章中看到他进行了多次ab测评后取结果的平均值.但是他列出来这样一个结果:

  1. 版本 函数测试 不实例化类 实例化类 类的继承
  2. PHP 4.4.2 1047.23/rps 1034.98/rps 1006.14/rps 992.95/rps
  3. PHP 5.2.1 1176.06/rps 1197.17/rps 1187.93/rps 1128.54/rps

这大致可以说明,php5.2确实是比php4.4.2要快.但是从1197.17>1176.06得出php5的类跑得比functiong还快,我不这么认为.只是21个request的差别,太小了,ab测试的随便一个风吹草吹就行了(而且说class比function要快,严重地伤害了我的感情,哈哈)…
嗯,先整这么多.有空好好研究一下,如何对web程序进行性能测评.
另外,有空见到这两位兄台,好好争论一番.

老覃的性能测试(2)

08月 21, 2007 on 2:07 am | In 未分类 | 4 Comments

我又写了一个文件.再测之:

  1. <?php
  2.  
  3. function signin()
  4. {
  5. return "null";
  6. }
  7. class User
  8. {
  9.     public function signin()
  10.     {
  11. return "null";
  12.     }
  13.  
  14. }
  15. function time1()
  16. {
  17. $arr=split(" ",microtime());
  18. return $arr[1]+$arr[0];
  19. }
  20. $t1= time1();
  21. for($i=0;$i<100000;$i++)
  22. signin();
  23. $t2=time1();
  24.  
  25. for($i=0;$i<100000;$i++)
  26. User::signin();
  27. $t3=time1();
  28.  
  29. echo "
  30. function:".($t2-$t1)."ms
  31. class:".($t3-$t2)."ms";

这是结果:

  1. function:0.071924924850464ms
  2. class:0.23149108886719ms

为了避免程序运行顺序的影响,我们再运行一次,这次先测静态类的,再测function的:

  1. <?php
  2.  
  3. function signin()
  4. {
  5. return "null";
  6. }
  7. class User
  8. {
  9.     public function signin()
  10.     {
  11. return "null";
  12.     }
  13.  
  14. }
  15. function time1()
  16. {
  17. $arr=split(" ",microtime());
  18. return $arr[1]+$arr[0];
  19. }
  20. $t1= time1();
  21.  
  22. for($i=0;$i<100000;$i++)
  23. User::signin();
  24. $t2=time1();
  25.  
  26. for($i=0;$i<100000;$i++)
  27. signin();
  28. $t3=time1();
  29.  
  30. echo "
  31. function:".($t3-$t2)."ms
  32. class:".($t2-$t1)."ms";

这次测的时间如下:

  1. function:0.072422027587891ms
  2. class:0.26213884353638ms

从这个结果来看,php的function还是相当快的,比class,哪怕是静态方法要快。
看来我越来越喜欢用function的路子是对的。

后来我加上另一个,把整个结果贴出来:

  1. $obj=& new User();
  2.  
  3. $t1= time1();
  4.  
  5. for($i=0;$i<100000;$i++)
  6. User::signin();
  7. $t2=time1();
  8.  
  9. for($i=0;$i<100000;$i++)
  10. signin();
  11. $t3=time1();
  12.  
  13. for($i=0;$i<100000;$i++)
  14. $obj->signin();
  15. $t4=time1();
  16.  
  17. for($i=0;$i<100000;$i++)
  18. {
  19. $obj1=& new User();
  20. $obj1->signin();
  21. }
  22. $t5=time1();
  23. echo "
  24. function:".($t3-$t2)."ms
  25. class:".($t2-$t1)."ms
  26. object:".($t4-$t3)."ms
  27. new object:".($t5-$t4)."ms";

结果是:

  1. function:0.071459054946899ms
  2. class:0.23710894584656ms
  3. object:0.08794093132019ms
  4. new object:0.17567801475525ms

也就是说,直接调用function是最快的,其次是重复调用已存在对象的方法,仅比纯function慢一点点。
接着是先新建class的实例再调用方法,最慢的是直接调用静态方法。
这个结果有一点点出乎我的意料,我没料到静态方法是最慢的一个。

老覃的性能测试

08月 21, 2007 on 1:33 am | In php性能 | No Comments

老覃同学做了一个测试,来比较PHP5下利用function,class来编程时的效率差异。
我一向喜欢钻牛角尖:
有两个疑问:
1.ab本身的文档说了,ab自身是需要CPU资源的,有时候要注意你可能不是在测apache的性能,而是在测ab这个软件的性能。老覃同志如何去除ab的影响?
2.php编译时也是花费CPU时间的。我做了另一组测试:

  1. //t1.php

function signin()

{

echo “signin”;

}

signin();

?>

ab -n 10000 -c 50 的结果是:
1534.15 [#/sec]
Time per request: 32.591 [ms] (mean)

,再另外一个:

function signin()

{

echo “signin”;

}

//signin();

?>

ab -n 10000 -c 50的结果是:
1748.48 [#/sec], Time per request: 28.596 。
就是说,算上ab的花费,apache的花费,php编译的花费,这几个的时间消费可能已经比php代码运行的时间花费要大了。加上运行的代码后,只相关几个ms。
如果要进行精确的比较,老覃的做法可能很不可靠。
PHP4与PHP5.20的效率目前还只有看官方的数据。
另外有个疑问,我的php比老覃同志的似乎快了不少,相差好几倍。可能是我的是Fedora 下运行的结果。

附注:

我后来做了一个实验,ab -n 10000 -c 50 http://localhost/test/23442.php ,返回的结果是:

  1. Requests per second:    2192.03 [#/sec] (mean)
  2. Time per request:       22.810 [ms] (mean)

这是在请求的文件不存在下,apache简单返回一个静态面的情况下的。由此看来,ab和apache的开销就已经占了大约20ms.

再注,在这里
是老覃的同事做的测试.我google得到了这个结果.

聪明人的算法

08月 15, 2007 on 12:48 am | In php性能 | 3 Comments

两段代码,都是用来1到100之前计算三次方的.
同样的代码,第一个其实只需要一行(当然要考虑美观,分成了四行);
第二个估计要用上100来行;但是哪个更快呢?….
读者说哪个程序更好?

  1.  

function getPower($n)
{
return $n*$n*$n;
}

global $data;
$data=array(
1=>1,
2=>8,
3=>27,
4=>64,
5=>125…
);
function getPower($n)
{
global $n;
return $data[$n];
}

php-APC介绍

08月 14, 2007 on 10:20 pm | In php性能 | 1 Comment

前面几篇文章提到了APC.很多人问我:APC是什么?这里做个比较全面的介绍:
APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”,但我个人觉得应该叫”另一个PHP缓存”.因为这个东西如果叫”可选PHP缓存”,容易给人一种可要可不要的,不怎么有用的错觉.
APC的主页是:<a href=”http://pecl.php.net/package/apc” mce_href=”http://pecl.php.net/package/apc”>http://pecl.php.net/package/apc</a>.目前的版本是3.0.14,通过PECL安装,需要php4.3.0或更高版本.
<b>APC的安装:</b>
一般是下载源代码然后phpize来编译安装,安装完以后在加上php.ini里加上
<coolcode>
extension=apc.so
</coolcode>
这么一行就行了.
<b>APC的使用</b>
APC的使用其实倒说不上.APC是个优化器,自安装之日起,就默默地在后台为您的PHP应用服务了.您的所有PHP代码会被缓存起来.

另外,APC可提供一定的内存缓存功能.但是这个功能并不是十分完美,有报告说如果频繁使用APC缓存的写入功能,会导致不可预料的错误.如果想使用这个功能,可以看看apc_fetch,apc_store等几个与apc缓存相关的函数.
从PHP5.2开始,APC引入了一个小甜饼,解决了困扰大家已久的大文件上传的进度条问题.具体请看看我这篇<a href=”http://www.162cm.com/archives/406.html” mce_href=”http://www.162cm.com/archives/406.html”>blog</a>.
<b>APC的高级使用</b>
1.缓存期限:
APC的缓存分两部分:系统缓存和用户数据缓存.
系统缓存是自动使用的,是指APC把PHP文件源码的编译结果缓存起来,然后在再次调用时先对比时间标记。如果未过期,则使用缓存代码运行。默认缓存3600s(一小时).但是这样仍会浪费大量CPU时间.因此可以在php.ini中设置system缓存为永不过期(apc.ttl=0).不过如果这样设置,改运php代码后需要restart一下您的web服务器(比如apache…).目前对APC的性能测试一般指的是这一层cache;
用户数据缓存由用户在编写php代码时用apc_store和apc_fetch函数操作读取、写入的.如果量不大的话我建议可以使用一下.如果量大,我建议使用memcache会更好.
如果要享受APC带来的缓存大文件上传进度的特性,需要在php.ini中将apc.rfc1867设为1,并且在表单中加一个隐藏域APC_UPLOAD_PROGRESS,这个域的值可以随机生成一个hash,以确何唯一.具体例子请参见前面给出的链接.
2.状态控制和分析:
APC的源码包自带了一个apc.php;您可以将这个文件上传到web服务器的某个目录下,用浏览器访问,这会显示当前的状态.我们可以从这里的表格分析当前的缓存状况,作出进一步优化.
apc-info-clublocalhost2.png
这是某test站点的状态.您可以慢慢分析,这个工具会提供很多有用的工具.比如您可以看到哪些文件经常被包含(访问),您缓存的哪个变量经常被读取,或经常被更新等.
最后顺便提一句,有独立报告说,APC的代码缓存、优化效果要高出zend优化器.就算不是真的,他开源而又免费,实在是一个相当不错的选择.

phpfox全攻略

08月 13, 2007 on 11:47 pm | In php性能 | 1 Comment

phpfox是国外的一款社区软件,具有论坛,博客,相册,音乐,投票,问答,视频等功能,基于php,mysql.安装需要gd库的支持。

我拿到程序后修改的第一步:

1.修改用户接口部分。 phpfox是典型的单入口型程序和类MVC架构。具体怎么改我不加描述了,只提一下,因为phpfox把对几乎所有路径的访问全部rewrite到了index.php,所以要在.htaccess文件中加上这样的两行:

  1. Rewritecond %{REQUEST_FILENAME} !-f
  2. Rewritecond %{REQUEST_FILENAME} !-d

一共要加两次(针对1.5,1.6这两个版本)。如果没有启用rewrite,就没有这会事。用户分别是{PREFIX}_user表,如果自行进行数据整合,操作这个表就可以了。
2.汉字在显示时有问题,需要看以下这些模板:

design/./templates/default/_modules/Menu/TabbedMenu.html
design/./templates/default/_modules/Listing/ListingCreate.html
design/./templates/default/_modules/Listing/ListingCreate.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Account/ProfileSettings.html
design/./templates/default/_modules/Ads/AdsList.html
design/./templates/default/_modules/Event/Calendar.html
design/./templates/default/_modules/Event/AddForm.html
design/./templates/default/_modules/Event/AddForm.html
design/./templates/default/_modules/Event/AddForm.html
design/./templates/default/_modules/Event/AddForm.html
design/./templates/default/_modules/Event/AddForm.html
design/./templates/default/_modules/Event/FeaturedEvents.html
design/./templates/default/_modules/Event/FeaturedEvents.html
design/./templates/default/_modules/Event/EventView.html
design/./templates/default/_modules/Event/EditForm.html
design/./templates/default/_modules/Event/EditForm.html
design/./templates/default/_modules/Event/EditForm.html
design/./templates/default/_modules/Event/EditForm.html
design/./templates/default/_modules/Event/EditForm.html
design/./templates/default/_modules/Video/Main.html
design/./templates/default/_modules/Video/AjaxBox.html
design/./templates/default/_modules/Video/ModifyCategories.html
design/./templates/default/_modules/Video/ApproveVideos.html
design/./templates/default/_modules/Video/AjaxLatest.html
design/./templates/default/_modules/Video/Categories.html
design/./templates/default/_modules/Video/Browse.html
design/./templates/default/_modules/Video/View.html
design/./templates/default/_modules/Blog/NewBlogs.html
design/./templates/default/_modules/Blog/MemberBlogs.html
design/./templates/default/_modules/Blog/AddBlog.html
design/./templates/default/_modules/Blog/MyPageBlogs.html
design/./templates/default/_modules/Blog/MyPageBlogView.html
design/./templates/default/_modules/Blog/BlogList.html
design/./templates/default/_modules/Blog/BlogList.html
design/./templates/default/_modules/Blog/BlogList.html
design/./templates/default/_modules/Blog/BlogList.html
design/./templates/default/_modules/Blog/EditBlog.html
design/./templates/default/_modules/Blog/EditBlog.html
design/./templates/default/_modules/Blog/View.html
design/./templates/default/_modules/Blog/View.html
design/./templates/default/_modules/Groups/GroupForumPosts.html
design/./templates/default/_modules/Groups/NewGroups.html
design/./templates/default/_modules/Groups/GroupDetails.html
design/./templates/default/_modules/Shoutbox/Box.html
design/./templates/default/admin/language/options.html
design/./templates/default/admin/language/options.html
design/./templates/default/admin/language/options.html
design/./templates/default/admin/language/missing-options.html
design/./templates/default/admin/language/add-phrase.html
design/./templates/default/admin/language/add-phrase.html
design/./templates/default/admin/language/phrases.html
design/./templates/default/admin/language/phrases.html
design/./templates/default/admin/language/phrases.html
design/./templates/default/admin/language/add-option.html
design/./templates/default/admin/language/missing.html

里面会有<{$title|escape}>这样的句子。将”|escape”删掉即可修正汉字bug.
3.敏感词过滤:phpfox为了扩展性,是在显示时过滤的,没有这个必要。我们把显示层的过小滤去掉,然后在index.php的第一行就加上过滤(如果有post数据,将之过滤)。这样将过滤机制更改之后,CPU又节省不少。
4.未登陆用户cache层。对于未登陆用户,没必要时时都是显示最新的。又是在index.php的第一行加上过滤:如果用户未登陆且无post数据,则显示cache层的静态文件。有1%的机率更新cache.

优化之前:

Document
Path: /
Document Length: 23960 bytes
Concurrency Level: 1
Time taken for tests: 2.740130 seconds
Complete requests: 30
Failed requests: 0
Write errors: 0
Total transferred: 733950 bytes
HTML transferred: 718800 bytes
Requests per second: 10.95 [#/sec] (mean)
Time per request: 91.338 [ms] (mean)
Time per request: 91.338 [ms] (mean, ac

优化之后:

Server Software: Apache/2.2.4
Server Hostname: ***.com
Server Port:
80
Document Path: /
Document Length: 23960 bytes
Concurrency Level: 1
Time taken for tests: 0.32685 seconds
Complete requests: 30
Failed requests: 0
Write errors: 0
Total transferred: 730560 bytes
HTML transferred: 718800 bytes
Requests per second: 917.85 [#/sec] (mean)
Time per request: 1.090 [ms] (mean)
Time per request: 1.090 [ms] (mean, across
all concurrent requests)
Transfer rate: 21814.29
[Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0
0 0.0
0 0
Processing: 0 0
1.0 1 1
Waiting: 0
0 0.3
0 1
Total: 0
0 1.0
1 1

又节约了不少资源。

4。数据库结构修改:

a.phpfox_online_session,phpfox_online,phpfox_site_session的数据都不需要永久保存。直接改成内存表。

由于内存表不支持txt类型,因此将tinytxt,text类型的字段均改为varchar字段。

现在做的改动有:

phpfox_online:

user( tinytext) 改为:user(varchar(32)

page (tinytext )改为page(varchar(100)

ip(tinytext)改为(varchar(16) )

phpfox_site_session:

browser:改为varcahr(64)

host:改为varchar(32)

page:改为varchar(64)

referer:改为varchar(64).

这个改过之后我试了一下,有些字段长度还可以进一步改小,这样才能将session数据都做成内存表,速度又可以大上一层楼。
b.flashchat_templates
这个表非常搞笑,有2万条记录,好像是在”CAN I FUCK YOU”和”<srai>DO YOU WANT TO HAVE
SEX</srai>”类似的句子之间做替换。基本没用(尤其是对中文).依我的看法如果这个表能导致瓶颈,就清空掉好了。

c.flashchat_patterns
这个表巨大无比,有15万条记录。主要是英文。如果可以的话,可以给他瘦身一下。

d.mysql的连接方式为mysql_connect,这个可以修改为mysql_pconnect。视具体情况。
e.许多表没有加索引,最搞的是论坛的topic表没有给group_id这个字段加索引。真是让人郁闷。注意把数据库结构整个看一遍,挨个把屁股擦干净。

5.去掉title中的标识:

修改include/modules/Site/classes/PhpFox_ComponentSiteTitle.class.php
中,将第200行的:

198 if (App::removeBrand())

199 {

200 // $sTitle
.= ‘ (Powered by phpFoX)’;

201 }

改掉就行了。(提醒大家,phpfox不允许未付费用户去这个标识。去这个标识需要另付费75$.

好啦,现在他可以支撑1000人在线了(其实我还加装了php-apc,这个东东把php编译结果缓存起来,另外把图片等静态文件进行了分流)。

PHP 装上APC之后的问题:

07月 26, 2007 on 8:31 pm | In php性能 | No Comments

APC由于能够缓存文件上传进度,因此算是解决了一直以来困挠PHP开发人员的一个老大难,所以我也特别喜欢他了。如果对php实现文件上传进度条有困 难,可以看这里
不过今天发现,APC宣称的加速功能,其实也是一种缓存,而不是对编译方式,编译过程什么的进行了优化.
原因是,我把两个程序目录名称对调,结果发现,程序报错了.但是让人郁闷的是,错误提示是在一个已经不存在的文件的109行。后来不管怎么刷新,都是这个结果.后来只好重启web服务器了事.
看来,APC是把编译好的php文件存放在共享内存中,以后是每过一段特定时间才重新编译一次.对于已经运行的应用,这个将大大节省你的CPU占用(虽然PHP的编译已经非常非常地快了,开启APC缓存后,仍能大副度地加速你的PHP,因为php源文件不需要在每次调用时都要编译了).从原理上说,PHP已经被改造成了Jsp式的静态脚本.只是PHP+APC的组合比Jsp的还要快,因为JSP在运行时会不断检测JSP源文件是否已经被更新,不断检测XML配置文件是否被更新.
但是,调试期间可能需要重启Apache.
目前没有在Lighttpd下检测以FastCGI方式运行时加入APC对PHP性能的影响。

lighttpd with secdownload,构建安全高效的下载站(应对迅雷有高招了)

07月 12, 2007 on 11:53 pm | In 未分类 | 1 Comment

下载站是一类特殊的站点,站长们已经不需要为流量担心了。他们只需要担心服务器的负载了。尤其是现在迅雷等近乎掠压者的软件出现以后。
lighttpd是近来日渐流行的一个轻量级,着眼于高负载性能的开源的,免费的web服务器软件。在很多方面比如mod_rewrite方面与行业巨头apache很相似,
使得从apache往lighttpd上的迁移成本相对较低。
但是个人感觉,lighttpd还是着眼于高负载载上并不失灵活性。例如为了迎合日渐流行的在线视频站点如youtube类站点的胃口,还专门出一个针对flv下载的模块,
这个模块相当偏门。
lighttpd上还有一个专门针对下载站点的模块:mod_secdownload
根据其官方wiki文档,mod_secdownload有四个配置选项:

  1. secdownload.secret        = <string>
  2. secdownload.document-root = <string>
  3. secdownload.uri-prefix    = <string>  (default: /)
  4. secdownload.timeout       = <short>   (default: 60 seconds)

在这个模块出现以前,人们也曾有几个思路去应对盗链:
1.修改WEB应用。比如直接通过PHP读取文件内容,发送二进制码。由于发送过程完全可控,这个对访问者的控制完全准确,比如想限制只有登陆用户才可以下载等等,易如反掌。问题是,每一次下载都通过php进行,严重地影响了服务器的效率。磁盘IO,CPU占用都容易跑满。
2.编程实施,自行设计一些服务器模块。比如weidy同学以前好像做过IIS下的过滤器,思路是在IIS中通过插入Hook,检测对静态下载文件(zip,exe,rar等文件的HTTP请求头中是否存在一个特定的Cookie,而这个cookie是有有效期的。当然这是可以的,我还有更好的思路,那就是,自己写一个web server,你想干什么就干什么,你要加一个彩蛋以便每当有用户访问时都要你站长大人先按一下电话按键用户才可以继续下载都行…..问题是,不是所有人都会。而且,实施也是一大麻烦。
3.基于服务器的现有模块,依照某些访问特性,比如来源页面(HTTP_REFERER)进行限制。但是,现在的盗链网页已经非常聪明了,迅雷更聪明:它能精确地学习前人在下载该软件时的数据,模仿性地发送特定的HTTP_REFERER(说不定将来连COOKIE也一起发送),非常牛B.所以像车东简单地这样写上:

  1. RewriteEngine on
  2. RewriteCond %{HTTP_REFERER} !^http://(www\.)?niernier\.com/.*$ [NC]
  3. RewriteRule \.(mp3|rar)$ http://www.niernier.com/archives/000445.html [R=301,L]
  4. #RewriteLog "logs/rewrite.log"
  5. #RewriteLogLevel 3

已经没用了,当然用这个防止通过baidu搜mp3还是可以的,对迅雷,没用。某些牛X的网站好像也能突破这种简单的防盗链。

好了,现在看看light官方网站给出的办法:
首先,某些东西是一定要经常改变的.或者是Cookie,或者是URI,等等。而URI是最好操作的。
另外,URI中一定要有一个加密性的东西,在secdownload中,secdownload.secret选项就是让站长自行设置的一个密串。(当然这个密串要足够保密>>>)

然后,我们用PHP来生成软件下载链接:

  1. <?php
  2.  
  3. $secret = "verysecret";
  4. $uri_prefix = "/dl/";
  5.  
  6. # filename
  7. $f = "/secret-file.txt";
  8.  
  9. # current timestamp
  10. $t = time();
  11.  
  12. $t_hex = sprintf("%08x", $t);
  13. $m = md5($secret.$f.$t_hex);
  14.  
  15. # generate link
  16. printf('<a href="%s%s/%s%s">%s</a>',
  17.        $uri_prefix, $m, $t_hex, $f, $f);
  18. ?>

看到了吗?这个新的链接包含了md5后的密钥(“verysecret”,在lighttpd.conf中指出),同时包含了时间特征串。这个时间串与文件名,密钥一起参与了md5计算,以便对下载客户端提交的URI进行校验。如果不把时间放进去md5,客户端便可以假造URI,任意修改时间串。
还是把官方给的lighttpd.conf中的相关配置也给出:

  1. server.modules = ( ..., "mod_secdownload", ... )
  2.  
  3. secdownload.secret          = "verysecret"
  4. secdownload.document-root   = "/home/www/servers/download-area/"
  5. secdownload.uri-prefix      = "/dl/"
  6. secdownload.timeout         = 120

现在,把你所有的页面的链接改成用这个php操作运算过的新地址吧。这个新地址被正确地被lighttpd解码并进行传送。
有趣的是,如果访问的URL已经超时失效,lighttpd送出的头是“408 Request Timeout” ,这不是一个标准的HTTP协议头,这是为了欺骗一下客户端。

当然,没有什么能永远防止疯狂下载。更妥善一点的情况是,这个下载地址并不是在html中直接给出,而是通过javascript来写出。即便是这样,如果hacker们
愿意,他也可以让一个firefox在后端访问该页并解析javascript最后遍历dom节点…. 得到该地址。你的地址每2分钟就超时,他也可以每2分钟来造访一次,拿到新地址。但是 有几个网站能够得到这种级别的高手的青睐呢?

下一页 »

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^