PHP7被誉为新一代PHP。官方开发团队对Zend引擎底层做了很多修改,优化了PHP的性能。可以说这个版本的PHP7的主题是性能优化。过去,PHP以其快速的开发效率着称。普通网站都是IO密集型程序,瓶颈在MySQL,PHP的性能劣势体现不出来。但是在密集计算方面,比C/C++、Java等静态编译语言差几十倍甚至上百倍。此外,使用设计非常复杂的开发框架,如Symfony、Laravel等,程序的性能也会明显下降。现在随着PHP越来越流行,Facebook、新浪微博等超大型网站都在使用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所做的优化,能提升这么多性能。1、zval使用栈内存在Zend引擎和扩展中,经常需要创建一个PHP变量,底层是一个zval指针。以前的版本使用MAKE_STD_ZVAL从堆中动态分配一个zval内存。而PHP7可以直接使用栈内存。在PHP代码中创建的变量也进行了优化,PHP7直接在堆栈内存上预分配了zval。这样就省去了很多内存分配和内存管理的操作。PHP5zval*val;MAKE_STD_ZVAL(val);PHP7zval;其次,zend_string存储的是hash值,数组查询不再需要重复计算hashPHP7为字符串创建了一个新的类型zend_string。除了char*指针和长度之外,还增加了一个新的哈希字段,用于保存字符串的哈希值。数组是PHP中的核心数据结构。PHP程序中经常会有很多$array\[$key]操作。虽然hashtablelookup的时间复杂度是O(1),但是需要计算$key到hashvalue的转换。的。不仅是数组操作,其实在PHP底层访问类属性、类方法、函数时,首先要通过哈希表找到对应的指针,然后执行对应的操作。在PHP7之前,Zend引擎会花费大量的CPU时间来计算哈希值。事实上,PHP程序运行后,$key的值在大多数情况下是保持不变的。PHP7只是将这个hash值保存下来,下次直接使用,省去了很多hash计算操作,而且PHP的hashtable性能与C数组一致。从实际项目上对callgrind的性能分析,会发现alloc和hash这两个操作占据了相当大的CPU时间比例。经过PHP7优化,这两个操作占用的CPU时间已经大大减少。(注:zend_hash仍然占12%,因为整体CPU降低了,所以总的耗时减少了很多)3.直接把数据存储在hashtablebucket中PHP5的hashtable的每个元素都是一个Bucket*,而PHP7直接存储Bucket,减少内存申请次数,提高Cache命中率和内存访问速度。4、当zend_parse_parameters改为宏实现PHP的C扩展函数和PHP中的变量进行参数输入时,使用zend_parse_parameters()函数。该函数根据一个字符串参数找到PHP对应的zval指针,然后赋值。这个功能其实是有一定的性能消耗的。PHP7直接用宏替换了zend_parse_parameters函数。在C扩展中,不再需要使用zend_parse_parameters来逐一查找参数。宏展开后,自动实现参数赋值。仅此一项就可以提高5%的性能。5.新增4个OPCODECall_user_function、is_int/string/array、strlen,定义的函数在很多PHP程序中被广泛使用。PHP5以扩展功能的形式提供。在PHP7中,这四类函数被改为ZendVM的OPCODE指令,可以更快的执行。6.更多其他优化除了以上五个主要优化点外,PHP7还有其他更详细的性能优化。比如将int、float、bool等基本类型改成直接值复制,改进排序算法,PCRE带JIT,execute_data和opline使用全局寄存器等,PHP7的性能优化会继续。与PHP5.6相比,PHP7-alpha的性能提升了近3倍。以下是WordPress在PHP7上的表现:PHP7的新特性除了性能优化,PHP7还增加了两个重要的新特性。1.变量类型PHP7版本函数的参数和返回值增加了类型限制。为什么PHP要添加类型?这个特性其实是为PHP7.1的JIT特性做准备的。添加类型后,PHPJIT可以准确判断变量类型,生成最佳的机器指令。functiontest(int$a,string$b,array$c):int{//code}2.错误和异常。PHP程序出错后,Zend引擎会出现致命错误,过去终止程序。PHP7可以使用try/catch来捕获错误。底层使用Exeception而不是FatalError。这一特点表明PHP语言正在朝着更加规范的方向发展。应用层和底层抛出错误的方式都统一为异常。try{non_exists_func();}catch(EngineException$e){echo"Exception:{$e->getMessage()}\n";}3.匿名类$test=newclass("HelloWorld"){publicfunction__construct($greeting){$this->greeting=$greeting;}};PHP7与JIT原来PHP7性能优化的方向不是上面说的,而是JIT。JIT是justintime的缩写,意思是在运行时将指令转换为二进制机器码。Java语言的JVM引擎底层是利用JIT将Java字节码编译成二进制机器码执行。在PHP7的开发过程中,有一个基于JIT的中间版本。后来开发组发现使用JIT后对于实际项目并没有太大的性能提升,所以PHP7最终放弃了JIT方案,PHP7.0-final版本将不会携带JIT特性。但是如果是计算密集型的程序,就不一样了。使用JIT将PHPOpCode编译成机器码,运行的性能会大大提高。PHP官方开发团队在2014年底重启了JIT的开发,PHP的异步网络通信扩展SwoolePHP在大多数程序员心目中都是用于网站的。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=newswoole_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=newswoole_http_server("0.0.0.0",9501);$http->on('request',function($request,$response){$response->header("Content-Type","text/html;charset=utf-8");$response->end("
