稍显寒酸的一个PHP框架:supermin

我曾经很长时间不搞什么PHP框架(框架神马的最讨人厌鸟)
我身边很多哥们,都是PHP大牛,所以,每人都写了自己的PHP框架,所以,其实我用不管谁的框架看上去都挺得罪人的,嗯,于是我只能是啥框架也不用了.
不过前一阵团队某个人自己引入了一个框架,然后做完了一个项目,接下来就拍拍屁股走人鸟~~
于是我总结了几个规律,我称之为徐氏定律:

如果一个项目只有一个人全盘负责,这个人一定会离职;
如果一个项目你不盯着,一定会出问题;
如果让一个人自己负责一个东西,不搞个需求评审过一下,他肯定会假想一堆需求;
如果一个程序员去设计一个框架,他肯定想着跨平台,多引擎支持,肯定想着做到老少咸宜男女通吃.

于是我决定写一个真正够用的好用的框架,在公司内部强行推介一下,你可以不用框架,但是如果你要用的话必须用我的框架;没有经过一大堆同事的评审和我的许可,你不可以使用自己写的框架,尤其是,我们基本没有工夫让谁写个牛B的框架….
嗯,于是回家我就开始搞,用了两个晚上,加起来一共不到20个小时的时间,我的超小精框架出厂了,我一向猥琐,嗯,也给起了个猥琐的名字:SM.嗯,全称是:supermini. 几百行代码而已,但是我觉得已经够用了,主要封装两个东西,一个是数据库访问,可以帮您连数据库和拼凑sql语句,另一个东西是一个Form表单生成工具.
这是一个很有特色的框架,嗯,其实连框架都称不上,就一个600来行的小lib而已,都还没有在生产环境上进行过实验,所以暂时不放代码出来.不过这个小框架包含了我对PHP的理解,嗯,每一种框架都是作者的程序哲学的体现.先来个PPT介绍一下基本逻辑.这个PPT是HTML5做的,请用chrome观看.
详情请参见:”迷你PHP框架supermini简介”.

用PHP和xapian构建全文检索[转]

大约从07年起,本博客就不转载了;
这篇算是以译文发的,原文在:http://www.contentwithstyle.co.uk/content/searching-with-xapian-and-php
========邪恶的分割线============
有的时候呢,嗯 ,mysql 就是不够快;尤其是在做全文检索的时候.各个字段都得正确地检索才行,而当我们的各个字段带有不同的权重时,事情就马上变得特别复杂了,这时你就需要xapian来救急了.
Xapian是什么东东
xapian是一个全文检索库,就和lucene和sphinx一样;它需要从c++代码编译,比较底层;现在已经有直接可用的php,perl,python绑定可以用了.目前提供了redhat和ubuntu的包;你可以在Mac os上编译,还可以通过cygwin来在windows下运行.
示例脚本
我不想去解释why和how,我只想展示一个简单的脚本;我封装的php文件有点大,读者可以从下载;
db.sql

CREATE DATABASE `demo`;

CREATE TABLE `demo`.`demo` (
`id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`unique_key` VARCHAR( 255 ) NOT NULL ,
`name` VARCHAR( 255 ) NULL DEFAULT NULL ,
`summary` TEXT NULL DEFAULT NULL ,
`date` DATETIME NULL DEFAULT NULL ,
UNIQUE (`unique_key`));

INSERT INTO `demo`.`demo`
(`id`, `unique_key`, `name`, `summary`, `date`)
VALUES (NULL, ‘foo’, ‘foo’, ‘foo bar test’, ‘2008-11-05 00:00:00’),
(NULL , ‘bar’, ‘bar’, ‘test foo bar’, ‘2009-11-05 00:00:00’);

XapianWrapper.php

xapian_read_db = new XapianDatabase(self::SETTINGS_XAPIAN_DB);
$this->xapian_stemmer = new XapianStem(“english”);
$this->xapian_enquire = new XapianEnquire($this->xapian_read_db);
} catch(Exception $e) {
throw new Exception(‘Could initialize Xapian: ‘ . $e->getMessage());
}
}

private function xapian_init_writable() {
try{
$this->xapian_write_db = new XapianWritableDatabase(self::SETTINGS_XAPIAN_DB, Xapian::DB_CREATE_OR_OPEN);
$this->xapian_indexer = new XapianTermGenerator();
$this->xapian_stemmer = new XapianStem(“english”);
$this->xapian_indexer->set_stemmer($this->xapian_stemmer);
} catch(Exception $e) {
throw new Exception(‘Could initialize Xapian: ‘ . $e->getMessage());
}
}

private function mysql_init() {
$this->mysql_link = mysql_connect(self::SETTINGS_MYSQL_HOST, self::SETTINGS_MYSQL_USER, self::SETTINGS_MYSQL_PASS);
if (!$this->mysql_link) {
throw new Exception(‘Could not connect: ‘ . mysql_error());
}

$db_selected = mysql_select_db(self::SETTINGS_MYSQL_DB, $this->mysql_link);
if (!$db_selected) {
throw new Exception(‘Can’t use db : ‘ . mysql_error());
}
}

/**
* Index method
*
*/
public function index($params) {
$this->xapian_init_writable();
$this->mysql_init();

$start = microtime(true);

$response = new stdClass();
$response->indexed = array();

$offset = (isset($params[‘offset’])) ? intval($params[‘offset’]) : 0;
$count = (isset($params[‘count’])) ? intval($params[‘count’]) : self::DEFAULT_COUNT;
$sql = ‘SELECT * FROM ‘.self::SETTINGS_MYSQL_TABLE.’ LIMIT ‘ . $offset . ‘, ‘ . $count . ‘;’;

$result = mysql_query($sql);

if (!$result) {
throw new Exception(‘Invalid query: ‘ . mysql_error());
}

$this->xapian_write_db->begin_transaction();

while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$response->indexed[] = $this->index_row($row);
}

$this->xapian_write_db->commit_transaction();
mysql_free_result($result);
mysql_close($this->mysql_link);

return $response;
}

private function index_row($row) {
$doc = new XapianDocument();

$this->xapian_indexer->set_document($doc);
$this->xapian_indexer->index_text($row[‘name’],50);
$this->xapian_indexer->index_text($row[‘summary’], 1);

$GUID = self::XAPIAN_PREFIX_UID . $row[‘unique_key’];
$doc->add_term($GUID);

$doc->add_value(self::XAPIAN_FIELD_URL, $row[‘url’]);
$doc->add_value(self::XAPIAN_FIELD_DATE, date(‘Ymd’, strtotime($row[‘date’])));
$doc->add_value(self::XAPIAN_FIELD_UID, $row[‘unique_key’]);
$doc->add_value(self::XAPIAN_FIELD_NAME, $row[‘name’]);
$doc->add_value(self::XAPIAN_FIELD_SUMMARY, $row[‘summary’]);

$this->xapian_write_db->replace_document(strval($GUID), $doc);

$row_response = array();
$row_response[‘name’] = $row[‘name’];
$row_response[‘guid’] = $row[‘unique_key’];
$row_response[‘url’] = $row[‘url’];
return $row_response;
}

/**
* Delete method
*
*/
public function delete($params) {
$this->xapian_init_writable();

$this->xapian_write_db->begin_transaction();

$response = array();

foreach($params[‘items’] as $param_guid) {
$GUID = self::XAPIAN_PREFIX_UID . $param_guid;
$this->xapian_write_db->delete_document(strval($GUID));
$response[] = $param_guid;
}

$this->xapian_write_db->commit_transaction();
return $response;
}

/**
* Search method
*
*/
public function search($params) {
$this->xapian_init_readonly();

$start = microtime(true);

// queries array to later construct full query
$arr_queries = array();

// from date
if(!empty($params[‘date_from’])) {
$arr_queries[] = new XapianQuery(XapianQuery::OP_VALUE_GE, 6, date(‘Ymd’, strtotime($params[‘date_from’])));
}

// to date
if(!empty($params[‘date_to’])) {
$arr_queries[] = new XapianQuery(XapianQuery::OP_VALUE_LE, 6, date(‘Ymd’, strtotime($params[‘date_to’])));
}

// unique key
if(!empty($params[‘unique_key’])) {
$arr_queries[] = new XapianQuery(self::XAPIAN_PREFIX_UID . $params[‘unique_key’]);
}

// normal search query parsed
if(!empty($params[‘search’])) {
$qp = new XapianQueryParser();
$qp->set_stemmer($this->xapian_stemmer);
$qp->set_database($this->xapian_read_db);
$qp->set_stemming_strategy(XapianQueryParser::STEM_SOME);
$arr_queries[] = $qp->parse_query($params[‘search’]);
}

// Find the results for the query.
// construct final query
$query = array_pop($arr_queries);

foreach($arr_queries as $sq) {
$query = new XapianQuery(XapianQuery::OP_AND, $query, $sq);
}
$this->xapian_enquire->set_query($query);

// set the count to the specified params
$offset = (isset($params[‘offset’])) ? intval($params[‘offset’]) : 0;
$count = (isset($params[‘count’])) ? intval($params[‘count’]) : self::DEFAULT_COUNT;
$matches = $this->xapian_enquire->get_mset($offset, $count);

$response = new stdClass();
$response->result_count = $matches->get_matches_estimated();
$results = array();

$i = $matches->begin();
while (!$i->equals($matches->end())) {
$m = array();

$n = $i->get_rank() + 1;
$doc = $i->get_document();

$m[‘position’] = $n;
$m[‘url’] = $doc->get_value(self::XAPIAN_FIELD_URL);
$m[‘name’] = $doc->get_value(self::XAPIAN_FIELD_NAME);
$m[‘summary’] = $doc->get_value(self::XAPIAN_FIELD_SUMMARY);
$m[‘date’] = $doc->get_value(self::XAPIAN_FIELD_DATE);
$m[‘unique_key’] = $doc->get_value(self::XAPIAN_FIELD_UID);
$m[‘percent’] = $i->get_percent();

$results[count($results)] = $m;
$i->next();
}

$response->results = $results;
$end = microtime(true);

// runtime info
$response->execute = new stdClass();
$response->execute->call = ‘search’;
$response->execute->offset = $offset;
$response->execute->count = $count;
$response->execute->start = $start;
$response->execute->end = $end;
$response->execute->time = $end – $start;

// debug stuff
$response->execute->debug = $query->get_description();

return $response;
}
}

index.php

index(array());
print_r($res);

Search.php

‘foo’);
$res = $x->search($params);
print_r($res);

delete.php

array(‘foo’),
);
$res = $x->delete($params);
print_r($res);


使用示例:
您下载刚才的源码包后,就可以导入db.sql,并在命令里运行程序;

bash$ php index.php
stdClass Object
(
[indexed] => Array
(
[0] => Array
(
[name] => foo
[guid] => foo
[url] =>
)

[1] => Array
(
[name] => bar
[guid] => bar
[url] =>
)

)

)
bash$ php search.php
stdClass Object
(
[result_count] => 2
[results] => Array
(
[0] => Array
(
[position] => 1
[url] =>
[name] => foo
[summary] => foo bar test
[date] => 20081105
[unique_key] => foo
[percent] => 100
)

[1] => Array
(
[position] => 2
[url] =>
[name] => bar
[summary] => test foo bar
[date] => 20091105
[unique_key] => bar
[percent] => 50
)

)

[execute] => stdClass Object
(
[call] => search
[offset] => 0
[count] => 10
[start] => 1256674866.79
[end] => 1256674866.79
[time] => 0.000944852828979
[debug] => Xapian::Query(Zfoo:(pos=1))
)

)
bash$ php delete.php
Array
(
[0] => foo
)
bash$ php search.php
stdClass Object
(
[result_count] => 1
[results] => Array
(
[0] => Array
(
[position] => 1
[url] =>
[name] => bar
[summary] => test foo bar
[date] => 20091105
[unique_key] => bar
[percent] => 100
)

)

[execute] => stdClass Object
(
[call] => search
[offset] => 0
[count] => 10
[start] => 1256674876.02
[end] => 1256674876.02
[time] => 0.000872850418091
[debug] => Xapian::Query(Zfoo:(pos=1))
)

)

接下来,扩展您自己的程序来满足您的各种需求吧,欢迎反馈.好好地享受检索的乐趣吧.

PHP版的slow-query

slowphp是由本人开发的一个简单的PHP扩展。目的在于记录web server上执行时间过长的php脚本。用法和mysql上的slow query极为相似。
代码地址:http://github.com/xurenlu/slowphp/.本周内即可完成全部功能。
版本: 1.0
示例:在php.ini中加入:

extension=slowphp.so
[slowphp]
slowphp.long_query_time=3
slowphp.long_query_log=”/var/log/php_long_query.log”

然后重启yapache,运行一段时间后即可查看/var/log/php_long_query.php中记录下了慢脚本的启动时间,消耗时间和脚本路径。
下一步功能:
为了方便调试,下一步将在ini中多加这样两项配置:

slowphp.long_query_log_probability=0.0001
slowphp.long_query_lock_file=”/tmp/open_long_query”

功能分别为:
1.有0.0001的概率记录当前脚本执行时间。
2.有/tmp/open_long_query文件存在时才记录脚本运行文件。
这样一来能极大地方便线上脚本运行效率的监控。

整理了一份招PHP高级工程师的面试题

嗯,基本上这些题都答得好 那就…
直接上题.

1. 基本知识点

  1. HTTP协议中几个状态码的含义:503 500 401 200 301 302。。。
  2. Include require include_once require_once 的区别.
  3. PHP/Mysql中几个版本的进化史,比如mysql4.0到4.1,PHP 4.x到5.1的重大改进等等。
  4. HEREDOC介绍
  5. 写出一些php魔幻方法;
  6. 一些编译php时的configure 参数
  7. 向php传入参数的两种方法。
  8. (mysql)请写出数据类型(int char varchar datetime text)的意思; 请问varchar和char有什么区别;
  9. error_reporting 等调试函数使用
  10. 您是否用过版本控制软件? 如果有您用的版本控制软件的名字是?
  11. posix和perl标准的正则表达式区别;
  12. Safe_mode 打开后哪些地方受限.
  13. 写代码来解决多进程/线程同时读写一个文件的问题。
  14. 写一段上传文件的代码。
  15. Mysql 的存储引擎,myisam和innodb的区别。

2. web 架构,安全,项目经验

  1. 介绍xdebug,apc,eAccelerator,Xcache,Zend opt的使用经验。
  2. 使用mod_rewrite,在服务器上没有/archivers/567.html这个物理文件时,重定向到index.php?id=567 ,请先打开mod_rewrite.
  3. MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?
  4. 写出一种排序算法(原理),并说出优化它的方法。
  5. 请简单阐述您最得意的开发之作
  6. 对于大流量的网站,您采用什么样的方法来解决各页面访问量统计问题
  7. 您是否用过模板引擎? 如果有您用的模板引擎的名字是?
  8. 请介绍Session的原理,大型网站中Session方面应注意什么?
  9. 测试php性能和mysql数据库性能的工具,和找出瓶颈的方法。
  10. 正则提出一个网页中的所有链接.
  11. 介绍一下常见的SSO(单点登陆)方案(比如dedecms整合discuz的passport)的原理。
  12. 您写过的PHP框架的特点,主要解决什么问题,与其他框架的不同点。
  13. 大型的论坛/新闻文章系统/SNS网站在性能优化上有什么区别?
  14. 相册类应用:要求在浏览器中能同时选中并上传多个文件,图片要求能剪裁,压缩包在服务器端解压。能上传单个达50M的文件。上传过程中有进度条显示。每个图片能生成四种大小缩略图,视频文件要转成flv供flash播放。叙述要涉及的各类开源软件和简单用途。
  15. 一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。用程序模拟该过程。

3. unix/linux 基本使用

  1. linux下查看当前系统负载信息的一些方法。
  2. vim的基本快捷键。
  3. ssh 安全增强方法;密码方式和rsa key 方式的配置。
  4. rpm/apt/yum/ports 装包,查询,删除的基本命令。
  5. Makefile的基本格式,gcc 编译,连接的命令,-O0 和-O3区别。
  6. gdb,strace,valgrind的基本使用.

4. 前端,HTML,JS

  1. css盒模型。
  2. javascript中的prototype。
  3. javascript中this对象的作用域。
  4. IE和firefox事件冒泡的不同。
  5. 什么是怪异模式,标准模式,近标准模式。
  6. DTD的定义
  7. IE/firefox常用hack.
  8. firefox,IE下的前端js/css调试工具。

用fastCGI协议进行RPC调用

近来由于业务量急剧增长,业务种类越来越多,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

#!/bin/bash

## ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI=”/home/y/opt/lighttpd/bin/spawn-fcgi”

## ABSOLUTE path to the PHP binary
FCGIPROGRAM=”/home/y/opt/php/bin/php-cgi”

## TCP port to which to bind on localhost
FCGIPORT=”1026″

## number of PHP children to spawn
PHP_FCGI_CHILDREN=10

## maximum number of requests a single PHP process can serve before it is restarted
PHP_FCGI_MAX_REQUESTS=1000

## IP addresses from which PHP should access server connections
FCGI_WEB_SERVER_ADDRS=”127.0.0.1,192.168.2.10″

# allowed environment variables, separated by spaces
ALLOWED_ENV=”ORACLE_HOME PATH USER”

## if this script is run as root, switch to the following user
USERID=y
GROUPID=y

################## no config below this line

if test x$PHP_FCGI_CHILDREN = x; then
PHP_FCGI_CHILDREN=5
fi

export PHP_FCGI_MAX_REQUESTS
export FCGI_WEB_SERVER_ADDRS

ALLOWED_ENV=”$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS”

if test x$UID = x0; then
EX=”$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN”
else
EX=”$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN”
fi

# copy the allowed environment variables
E=

for i in $ALLOWED_ENV; do
E=”$E $i=${!i}”
done

# clean the environment and set up a new one
env – $E $EX

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

for($i=0;$i<100;$i++)
{
echo rand();
echo ‘….Scene of shooting at Nebraska shopping centre
Eight killed in Nebraska shooting
A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
Scene of shooting at Nebraska shopping centre
Eight killed in Nebraska shooting
A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
Scene of shooting at Nebraska shopping centre
Eight killed in Nebraska shooting
A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
Scene of shooting at Nebraska shopping centre
Eight killed in Nebraska shooting
A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
‘;
}
print “done!”;

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

include “./mod_fcgi.php”;
$fcgi=new mod_fcgi();
$args=”127.0.0.1:1026″;
$filename=”/home/y/www/qps/http.php”;
$fcgi->parser_open($args,$filename,$rq_err,$cgi_headers);
print($fcgi->parsed_output);
echo “n=============n”;

B:走CURL通道:

include “./curl.php”;
$curl=& new CURL();
echo $curl->get(“http://localhost/qps/http.php”);
echo “n=============n”;

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

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

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

Total transferred: 2244515 bytes
HTML transferred: 2240015 bytes
Requests per second: 204.18 [#/sec] (mean)
Time per request: 4.898 [ms] (mean)
Time per request: 4.898 [ms] (mean, across all concurrent requests)
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扩展).
因此,我忙活了半天,最后得出的结论是,目前还不能在公司大规模加以运用。
但是对于小型企业,创业型公司来说,这种效率对比还是很有用的,可以加以挖掘。

php文章收集贴

ab测试数据会跳舞
*php中静态方法,函数,对象方法性能测试
*php-APC介绍
*利用web应用中的不均衡性重构你的技术细节
*把握web 开发的平衡与不平衡
*php高手之路之—狐假虎威
*PHP高手之路之—折柳为剑
*php高手之路之—纵横天下
*php高手之路之—万人之术
*php高手之路之—屠龙宝刀
*php高手之路之—绝世秘籍
*php高手之路之—返樸归真
*用PHP5.2+APC实现超酷的PHP进度条
*道可道,非常道—PHP模板技术
select id,title from * 与select * from **的速度测试。
*为什么SELECT col1,col2,col3,col4 会比SELECT * 慢?

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

我的师兄,从某种程度上说也是我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/
第一份结果:

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
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的结果:

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
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).
第三份结果:

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
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).
第四份结果是:

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
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).
第五份结果是:

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
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测评后取结果的平均值.但是他列出来这样一个结果:

版本 函数测试 不实例化类 实例化类 类的继承
PHP 4.4.2 1047.23/rps 1034.98/rps 1006.14/rps 992.95/rps
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程序进行性能测评.
另外,有空见到这两位兄台,好好争论一番.