<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>waimv.com &#187; 内存</title>
	<atom:link href="http://www.waimv.com/tag/%e5%86%85%e5%ad%98/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.waimv.com</link>
	<description></description>
	<lastBuildDate>Fri, 09 Nov 2018 10:41:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>php性能分析</title>
		<link>http://www.waimv.com/php/201/</link>
		<comments>http://www.waimv.com/php/201/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 07:50:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[内存]]></category>
		<category><![CDATA[函数]]></category>
		<category><![CDATA[扩展]]></category>

		<guid isPermaLink="false">http://www.szpian.com/?p=201</guid>
		<description><![CDATA[1.缘起 关于PHP，很多人的直观感觉是PHP是一种灵活的脚本语言，库类丰富，使用简单，安全，非常适合WEB开发，但性能低下。PHP的性能是否真的就 如同大家的感觉一样的差呢?本文就是围绕这么一个话题来进行探讨的。从源码、应用场景、基准性能、对比分析等几个方面深入分析PHP之性能问题，并通过真 实的数据来说话。 2.从原理分析PHP性能 从原理分析PHP的性能，主要从以下几个方面：内存管理、变量、函数、运行机制来进行分析。 2.1内存管理 类似Nginx的内存管理方式，PHP在内部也是基于内存池，并且引入内存池的生命周期概念。在内存池方面，PHP对PHP脚本和扩展的所有内存相关操作都进行了托管。对大内存和小内存的管理采用了不同的实现方式和优化，具体可以参考以下文档：https://wiki.php.net/internals/zend_mm。在内存分配和回收的生命周期内，PHP采用一次初始化申请+动态扩容+内存标识回收机制，并且在每次请求结束后直接对内存池进行重新mask。 2.2变量 总所周知，PHP是一种弱变量类型的语言，所以在PHP内部，所有的PHP变量都对应成一种类型Zval，其中具体定义如下： 图一PHP变量 在变量方面，PHP做了大量的优化工作，比如说Reference counting和copy on writer机制。这样能够保证内存使用上的优化，并且减少内存拷贝次数(请参考http://blog.xiuwz.com/2011/11/09 /php-using-internal-zval/)。在数组方面，PHP内部采用高效的hashtable来实现。 2.3函数 在PHP内部，所有的PHP函数都回转化成内部的一个函数指针。比如说扩展中函数 ZEND_FUNCTION ( my_function );//类似function my_function(){} 在内部展开后就会是一个函数 void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS ); void zif_my_function( int ht, zval * return_value, zval * this_ptr, int return_value_used, zend_executor_globals * executor_globals ); 从这个角度来看，PHP函数在内部也是对应一个函数指针。 2.4运行机制 在话说PHP性能的时候，很多人都会说“C/C++是编译型，JAVA是半编译型，PHP是解释型”。也就是说PHP是先动态解析再代码运行的，所以从这个角度来看，PHP性能必然很差。 的确，从PHP脚本运行来输出，的确是一个动态解析再代码运行的过程。具体来说，PHP脚本的运行机制如下图所示： 图二 PHP运行机制 PHP的运行阶段也分成三个阶段： Parse。语法分析阶段。 Compile。编译产出opcode中间码。 Execute。运行，动态运行进行输出。 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>1.缘起</strong></p>
<p>关于PHP，很多人的直观感觉是PHP是一种灵活的脚本语言，库类丰富，使用简单，安全，非常适合WEB开发，但性能低下。PHP的性能是否真的就 如同大家的感觉一样的差呢?本文就是围绕这么一个话题来进行探讨的。从源码、应用场景、基准性能、对比分析等几个方面深入分析PHP之性能问题，并通过真 实的数据来说话。</p>
<p><strong> 2.从原理分析PHP性能</strong></p>
<p>从原理分析PHP的性能，主要从以下几个方面：内存管理、变量、函数、运行机制来进行分析。</p>
<p>2.1内存管理</p>
<p>类似Nginx的内存管理方式，PHP在内部也是基于内存池，并且引入内存池的生命周期概念。在内存池方面，PHP对PHP脚本和扩展的所有内存相关操作都进行了托管。对大内存和小内存的管理采用了不同的实现方式和优化，具体可以参考以下文档：https://wiki.php.net/internals/zend_mm。在内存分配和回收的生命周期内，PHP采用一次初始化申请+动态扩容+内存标识回收机制，并且在每次请求结束后直接对内存池进行重新mask。</p>
<p>2.2变量</p>
<p>总所周知，PHP是一种弱变量类型的语言，所以在PHP内部，所有的PHP变量都对应成一种类型Zval，其中具体定义如下：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100725724.jpg" alt="大话PHP之性能 " width="428" height="234" /></p>
<p>图一PHP变量</p>
<p>在变量方面，PHP做了大量的优化工作，比如说Reference counting和copy on writer机制。这样能够保证内存使用上的优化，并且减少内存拷贝次数(请参考http://blog.xiuwz.com/2011/11/09 /php-using-internal-zval/)。在数组方面，PHP内部采用高效的hashtable来实现。</p>
<p>2.3函数</p>
<p>在PHP内部，所有的PHP函数都回转化成内部的一个函数指针。比如说扩展中函数</p>
<p>ZEND_FUNCTION ( my_function );//类似function my_function(){}</p>
<p>在内部展开后就会是一个函数</p>
<p>void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );</p>
<p>void zif_my_function(</p>
<p>int ht,</p>
<p>zval * return_value,</p>
<p>zval * this_ptr,</p>
<p>int return_value_used,</p>
<p>zend_executor_globals * executor_globals</p>
<p>);</p>
<p>从这个角度来看，PHP函数在内部也是对应一个函数指针。</p>
<p>2.4运行机制</p>
<p>在话说PHP性能的时候，很多人都会说“C/C++是编译型，JAVA是半编译型，PHP是解释型”。也就是说PHP是先动态解析再代码运行的，所以从这个角度来看，PHP性能必然很差。</p>
<p>的确，从PHP脚本运行来输出，的确是一个动态解析再代码运行的过程。具体来说，PHP脚本的运行机制如下图所示：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100726281.jpg" alt="大话PHP之性能 " width="192" height="236" /></p>
<p>图二 PHP运行机制</p>
<p>PHP的运行阶段也分成三个阶段：</p>
<p>Parse。语法分析阶段。</p>
<p>Compile。编译产出opcode中间码。</p>
<p>Execute。运行，动态运行进行输出。</p>
<p>所以说，在PHP内部，本身也是存在编译的过程。并且据此产生了大量的opcode cache工具，比如说apc、eacc、xcache等等。这些opcode cache在生产环境基本上在标配。基于opcode cache，能到做到“PHP脚本编译一次，多次运行”的效果。从这点上，PHP就和JAVA的半编译机制非常类似。</p>
<p>所以，从运行机制上来看，PHP的运行模式和JAVA是非常类似的，都是先产生中间码，然后运行在不同虚拟机上。</p>
<p>2.5动态运行</p>
<p>从上面的几个分析来看，PHP在内存管理、变量、函数、运行机制等几个方面都做了大量的工作，所以从原理来看，PHP不应该存在性能问题，性能至少也应该和Java比较接近。</p>
<p>这个时候就不得不谈PHP动态语言的特性所带来的性能问题了，由于PHP是动态运行时，所以所有的变量、函数、对象调用、作用域实现等等都是在执行 阶段中才确定的。这个从根本上决定了PHP性能中很难改变的一些东西：在C/C++等能够在静态编译阶段确定的变量、函数，在PHP中需要在动态运行中确 定，也就决定了PHP中间码不能直接运行而需要运行在Zend Engine上。</p>
<p>说到PHP变量的具体实现，又不得不说一个东西了：Hashtable。Hashtable可以说在PHP灵魂之一，在PHP内部广泛用到，包含变量符号栈、函数符号栈等等都是基于hashtable的。</p>
<p>以PHP变量为例来说明下PHP的动态运行特点，比如说代码：</p>
<p>$var = “hello, blog.xiuwz.com”;</p>
<p>?&gt;</p>
<p>该代码的执行结果就是在变量符号栈(是一个hashtable)中新增一个项</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100726482.jpg" alt="大话PHP之性能 " width="451" height="25" /></p>
<p>当要使用到该变量时候，就去变量符合栈中去查找(也就是变量调用对出了一个hash查找的过程)。</p>
<p>同样对于函数调用也基本上类似有一个函数符号栈(hashtable)。</p>
<p>其实关于动态运行的变量查找特点，在PHP的运行机制中也能看出一些。PHP代码通过解释、编译后的流程下图：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100726861.jpg" alt="大话PHP之性能 " width="558" height="422" /></p>
<p>图3 PHP运行实例</p>
<p>从上图可以看出，PHP代码在compile之后，产出的了类符号表、函数符号表、和OPCODE。在真正执行的时候，zend Engine会根据op code去对应的符号表中进行查找，处理。</p>
<p>从某种程度上，在这种问题的上，很难找到解决方案。因为这是由于PHP语言的动态特性所决定的。但是在国内外也有不少的人在寻找解决方案。因为通过这样，能够从根本上完全的优化PHP。典型的列子有facebook的hiphop(https://github.com/facebook/hiphop-php)。</p>
<p>2.6结论</p>
<p>从上面分析来看，在基础的内存管理、变量、函数、运行机制方面，PHP本身并不会存在明显的性能差异，但由于PHP的动态运行特性，决定了PHP和 其他的编译型语言相比，所有的变量查找、函数运行等等都会多一些hash查找的CPU开销和额外的内存开销，至于这种开销具体有多大，可以通过后续的基准 性能和对比分析得出。</p>
<p>因此，也可以大体看出PHP不太适合的一些场景：大量计算性任务、大数据量的运算、内存要求很严格的应用场景。如果要实现这些功能，也建议通过扩展的方式实现，然后再提供钩子函数给PHP调用。这样可以减低内部计算的变量、函数等系列开销。</p>
<p><strong> 3.基准性能</strong></p>
<p>对于PHP基准性能，目前缺少标准的数据。大多数同学都存在感性的认识，有人认为800QPS就是PHP的极限了。此外，对于框架的性能和框架对性能的影响很没有响应的权威数字。</p>
<p>本章节的目的是给出一个基准的参考性能指标，通过数据给大家一个直观的了解。</p>
<p>具体的基准性能有以下几个方面：</p>
<p>1.裸PHP性能。完成基本的功能。</p>
<p>2.裸框架的性能。只做最简单的路由分发，只走通核心功能。</p>
<p>3.标准模块的基准性能。所谓标准模块的基准性能，是指一个具有完整服务模块功能的基准性能。</p>
<p>3.1环境说明</p>
<p>测试环境：</p>
<p>Uname -a</p>
<p>Linux db-forum-test17.db01.baidu.com 2.6.9_5-7-0-0 #1 SMP Wed Aug 12 17:35:51 CST 2009 x86_64 x86_64 x86_64 GNU/Linux</p>
<p>Red Hat Enterprise Linux AS release 4 (Nahant Update 3)</p>
<p>8 Intel(R) Xeon(R) CPU E5520 @ 2.27GHz</p>
<p>软件相关：</p>
<p>Nginx：</p>
<p>nginx version: nginx/0.8.54 built by gcc 3.4.5 20051201 (Red Hat 3.4.5-2)</p>
<p>Php5：(采用php-fpm)</p>
<p>PHP 5.2.8 (cli) (built: Mar 6 2011 17:16:18)</p>
<p>Copyright (c) 1997-2008 The PHP Group</p>
<p>Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies</p>
<p>with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator</p>
<p>bingo2：</p>
<p>PHP框架。</p>
<p>其他说明：</p>
<p>目标机器的部署方式：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100726885.jpg" alt="大话PHP之性能 " width="184" height="32" /></p>
<p>脚本。</p>
<p>测试压力机器和目标机器独立部署。</p>
<p>3.2裸PHP性能</p>
<p>最简单的PHP脚本。</p>
<p>require_once ‘./actions/indexAction.php’;</p>
<p>$objAction = new indexAction();</p>
<p>$objAction-&gt;init();</p>
<p>$objAction-&gt;execute();</p>
<p>?&gt;</p>
<p>Acitons/indexAction.php里面的代码如下</p>
<p>class indexAction</p>
<p>{</p>
<p>public function execute()</p>
<p>{</p>
<p>echo ‘hello, world!’;</p>
<p>}</p>
<p>}</p>
<p>?&gt;</p>
<p>通过压力工具测试结果如下：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100729745.jpg" alt="大话PHP之性能 " width="467" height="104" /></p>
<p>3.3裸PHP框架性能</p>
<p>为了和3.2的对比，基于bingo2框架实现了类似的功能。代码如下</p>
<p>require_once ‘Bingo/Controller/Front.php’;</p>
<p>$objFrontController = Bingo_Controller_Front::getInstance(array(</p>
<p>‘actionDir’ =&gt; ‘./actions’,</p>
<p>));</p>
<p>$objFrontController-&gt;dispatch();</p>
<p>压力测试结果如下：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100730519.jpg" alt="大话PHP之性能 " width="375" height="107" /></p>
<p>从该测试结果可以看出：框架虽然有一定的消耗，但对整体的性能来说影响是非常小的。</p>
<p>3.4标准PHP模块的基准性能</p>
<p>所谓标准PHP模块，是指一个PHP模块所必须要具体的基本功能：</p>
<p>路由分发。</p>
<p>自动加载。</p>
<p>LOG初始化&amp;Notice日志打印。所以的UI请求都一条标准的日志。</p>
<p>错误处理。</p>
<p>时间校正。</p>
<p>自动计算每个阶段耗时开销。</p>
<p>编码识别&amp;编码转化。</p>
<p>标准配置文件的解析和调用</p>
<p>采用bingo2的代码自动生成工具产生标准的测试PHP模块：test。</p>
<p>测试结果如下：</p>
<p><img src="http://www.php100.com/uploadfile/2011/1201/20111201100730697.jpg" alt="大话PHP之性能 " width="372" height="182" /></p>
<p>3.5结论</p>
<p>从测试数据的结论来看，PHP本身的性能还是可以的。基准性能完全能够达到几千甚至上W的QPS。至于为什么在大多数的PHP模块中表现不佳，其实 这个时候更应该去找出系统的瓶颈点，而是简单的说OK，PHP不行，那我们换C来搞吧。(下一个章节，会通过一些例子来对比，采用C来处理不见得有特别的 优势)</p>
<p>通过基准数据，可以得出以下几个具体的结论：</p>
<p>1.PHP本身性能也很不错。简单功能下能够达到5000QPS，极限也能过W。</p>
<p>2.PHP框架本身对性能影响非常有限。尤其是在有一定业务逻辑和数据交互的情况下，几乎可以忽略。</p>
<p>3.一个标准的PHP模块，基准性能能够达到2000QPS(80 cpu idle)。</p>
<p>4.对比分析</p>
<p>很多时候，大家发现PHP模块性能不行的时候，就来一句“ok，我们采用C重写吧”。在公司内，采用C/C++来写业务逻辑模块的现象到处都有，在前几年甚至几乎全部都是采用C来写。那时候大家写的真是一个痛苦：调试难、敏捷不要谈。</p>
<p><a href="http://sd.csdn.net/a/20111130/308320.html">http://sd.csdn.net/a/20111130/308320.html</a></p>
<p><a href="http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2011/1201/9391.html">http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2011/1201/9391.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.waimv.com/php/201/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
