您好,欢迎访问一九零五行业门户网

【天赢金创】PHP7与Swoole

原文:http://rango.swoole.com/archives/440
最近php官方终于发布了传说中的php7,虽然只是alpha版。php7号称是新一代的php,官方开发组对zend引擎底层做了大量修改来优化php的性能。可以说php7这个版本的主题就是性能优化。
在过去php一直以开发效率快著称,而语言本身的性能较差(当然比python,ruby还是要快一些的)。普通的web网站都是io密集型的程序,瓶颈在mysql上,所以体现不出php的性能劣势。但在密集计算方面比c/c++、java等静态编译语言差几十倍甚至上百倍。另外使用设计非常复杂的开发框架,如symfony、laravel等,程序性能也会明显下降。
现在随着php越来越流行,像facebook、新浪微博这样超大型规模的网站都在使用php。php语言性能问题就越来越严重了。facebook有几十万台服务器,如果现有的php程序可以提升一部分性能,将会节约大量的服务器资源。所以就有了hhvm、hack。hack为php增加了类型,hhvm是一个重新设计的php引擎,实际项目中使用hhvm可以提近70%的性能。实际项目70%性能提升这是一个什么概念?腾讯qq农场最初使用php开发,后因为性能问题使用c语言重构,完成后性能提升了100%。
php官方也注意到了这个问题,所以就有了php7的开发计划。最新公布的php7-alpha在wordpress项目中测试的表现已经超越了hhvm。未来php将会同时具备极高的开发效率和极高的性能,再结合swoole做异步编程,php势必会更加流行。
本文简单介绍一下php7做了哪些优化,可以提升如此多性能。
一 zval使用栈内存
在zend引擎和扩展中,经常要创建一个php的变量,底层就是一个zval指针。之前的版本都是通过make_std_zval动态的从堆上分配一个zval内存。而php7可以直接使用栈内存。php代码中创建的变量也进行了优化,php7直接在栈内存上预分配zval。这样节约了大量内存分配和内存管理的操作。
php5
zval *val; make_std_zval(val);
php7
zval val;
二 zend_string存储hash值,array查询不再需要重复计算hash
php7为字符串单独创建了新类型叫做zend_string,除了char *指针和长度之外,增加了一个hash字段,用于保存字符串的hash值。php中array是核心数据结构,php程序中往往都有大量的$array[$key]操作,虽然hashtable查找的时间复杂度是o(1),但$key要转为hash值是要经过计算的。不仅仅是array操作,实际上php底层对于类属性、类方法、函数,访问时都要先通过hashtable查找到对应的指针,再执行对应的操作。php7之前zend引擎会有大量的cpu时间用于计算hash值。
实际上php程序运行起来之后,大部分情况下$key的值都是不变的。php7干脆将这个hash值保存起来,下次直接使用,这样就节省了大量的hash计算操作,php的hashtable与c数组的性能一致。
从实际项目进行callgrind性能分析,会发现alloc和hash 2项操作就占用了相当大比例的cpu时间。php7优化之后这2项操作占用的cpu时间降低了非常多。(注:zend_hash仍然占12%,因为整体cpu降低了,所以总的耗时降低了不少)
三 hashtable桶内直接存数据
php5的hashtable每个元素都是一个 bucket *,而php7直接存bucket,减少了内存申请次数,提升了cache命中率和内存访问速度。
四 zend_parse_parameters改为宏实现
php的c扩展函数与php中的变量进行参数输入时,要使用zend_parse_parameters()函数,这个函数根据一个字符串参数找到对应php的zval指针,然后进行赋值。 这个函数实际上有一定的性能消耗。php7直接使用宏替换了zend_parse_parameters函数,c扩展中不再需要使用zend_parse_parameters进行逐个参数的查找,宏展开后自动会实现参数赋值。仅此一项就提升了5%的性能。
五 新增加4种opcode
很多php程序中会大量使用call_user_function, is_int/string/array, strlen , defined 函数。php5 都是以扩展函数的方式提供,php7中这4类函数改成zendvm的opcode指令,执行更快。
六 其他更多优化
除了上面5个主要优化点之外,php7还有其他更多的细节性能优化。如基础类型int、float、bool等改为直接进行值拷贝,排序算法改进,pcre with jit,execute_data和opline使用全局寄存器等等。php7对性能的优化会继续进行下去。
php7-alpha相比php5.6性能提升了近3倍。下面是wordpress在php7上的表现:
php7的新特性
除了性能优化外,php7新增加了2项重要的新特性。
变量类型
php7版本函数的参数和返回值增加了类型限定。为什么php要加入类型,实际上此项特性是为了php7.1版本的jit特性做准备,增加类型后php jit可以准确判断变量类型,生成最佳的机器指令。
function test(int $a, string $b, array $c) : int {
//code
}
错误异常
php程序出错后过去zend引擎会发生致命错误并终止程序运行,php7可以使用try/catch捕获错误。底层使用exeception代替了fatal error。这个特性表示php语言正在向一个更加规范的方向发展。应用层与底层在错误抛出的方式全部统一为异常。
try {
non_exists_func();
} catch (engineexception $e) {
echo exception: {$e->getmessage()}\n;
}
匿名类
$test = new class(hello world) {
public function __construct($greeting) {
$this->greeting = $greeting;
}
};
php7与jit
最初php7性能优化的方向并不是以上所讲的,而是jit。jit是just in time的缩写,表示运行时将指令转为二进制机器码。java语言的jvm引擎底层就是使用jit将java字节码编译为二进制机器码执行。php7开发过程中有一个中间版本是基于jit,后来开发组发现使用jit后,对于实际项目并没有有太大的性能提升,所以php7最终放弃了jit方案,php7.0-final版本不会携带jit特性。
但如果是密集计算类程序就不同了,使用jit将php opcode编译为机器码,运算的性能会大幅提升。php官方开发组在2014年底重启了jit的开发工作。
php的异步网络通信扩展swoole
php在大部分程序员印象中都是用来做web网站的。php没有像python的twisted、tornado,java的netty、mina,javascript的node.js等框架,无法实现异步网络通信程序。php的swoole扩展就是为了弥补此项缺陷而诞生的开源项目。swoole是一个标准的php扩展,为php提供了一系列异步io、事件驱动、并行数据结构功能。
swoole与node.js非常相似,不同之处是swoole在并行提供了底层支持。node.js是一个单进程单线程的程序,在多核服务器上无法发挥全部cpu核的计算能力。需要程序员自行使用child_process/cluster扩展或者启动多实例,使程序能够利用到多核优势。而swoole在底层就支持了多线程/多进程,程序启动后就会创建好多个io线程和多个worker进程。程序员仅需配置线程/进程数量即可。
使用swoole开发的tcp服务器程序:
$serv = new swoole_server(127.0.0.1, 9501);
$serv->on('connect', function ($serv, $fd){
echo client:connect.\n;
});
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, $data);
});
$serv->on('close', function ($serv, $fd) {
echo client: close.\n;
});
$serv->start();
swoole同样也内置了http_server和websocket服务器的支持。swoole_http_server与传统的php-fpm不同,它是在php内进行事件循环的,基于swoole_http_server完全可以开发出类似java应用服务器一样,可以控制完整对象生命周期的程序。swoole_http_server天然支持异步io,可以很方便的实现支持大量tcp连接的comet服务。swoole_websocket_server可以用来实现支持web实时推送的程序。
使用swoole的web服务器程序:
$http = new swoole_http_server(0.0.0.0, 9501);
$http->on('request', function ($request, $response) {
$response->header(content-type, text/html; charset=utf-8);
$response->end(
hello swoole. #.rand(1000, 9999).
);
}); $http->start();
php的未来
可以预见php语言未来会在性能方面有明显的提升,越来越接近c/c++、java等静态编译语言。再加上swoole扩展,php的使用范围可以扩展到移动通信、云计算、网络游戏、物联网、车联网、智能家居等领域。
php虽然未必是最好的编程语言,但php在向着这个方向在发展。
其它类似信息

推荐信息