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。运行,动态运行进行输出。
所以说,在PHP内部,本身也是存在编译的过程。并且据此产生了大量的opcode cache工具,比如说apc、eacc、xcache等等。这些opcode cache在生产环境基本上在标配。基于opcode cache,能到做到“PHP脚本编译一次,多次运行”的效果。从这点上,PHP就和JAVA的半编译机制非常类似。
所以,从运行机制上来看,PHP的运行模式和JAVA是非常类似的,都是先产生中间码,然后运行在不同虚拟机上。
2.5动态运行
从上面的几个分析来看,PHP在内存管理、变量、函数、运行机制等几个方面都做了大量的工作,所以从原理来看,PHP不应该存在性能问题,性能至少也应该和Java比较接近。
这个时候就不得不谈PHP动态语言的特性所带来的性能问题了,由于PHP是动态运行时,所以所有的变量、函数、对象调用、作用域实现等等都是在执行 阶段中才确定的。这个从根本上决定了PHP性能中很难改变的一些东西:在C/C++等能够在静态编译阶段确定的变量、函数,在PHP中需要在动态运行中确 定,也就决定了PHP中间码不能直接运行而需要运行在Zend Engine上。
说到PHP变量的具体实现,又不得不说一个东西了:Hashtable。Hashtable可以说在PHP灵魂之一,在PHP内部广泛用到,包含变量符号栈、函数符号栈等等都是基于hashtable的。
以PHP变量为例来说明下PHP的动态运行特点,比如说代码:
-
<?php
- $var = “hello, blog.xiuwz.com”;
- ?>
该代码的执行结果就是在变量符号栈(是一个hashtable)中新增一个项
当要使用到该变量时候,就去变量符合栈中去查找(也就是变量调用对出了一个hash查找的过程)。
同样对于函数调用也基本上类似有一个函数符号栈(hashtable)。
其实关于动态运行的变量查找特点,在PHP的运行机制中也能看出一些。PHP代码通过解释、编译后的流程下图:
图3 PHP运行实例
从上图可以看出,PHP代码在compile之后,产出的了类符号表、函数符号表、和OPCODE。在真正执行的时候,zend Engine会根据op code去对应的符号表中进行查找,处理。
从某种程度上,在这种问题的上,很难找到解决方案。因为这是由于PHP语言的动态特性所决定的。但是在国内外也有不少的人在寻找解决方案。因为通过这样,能够从根本上完全的优化PHP。典型的列子有facebook的hiphop(https://github.com/facebook/hiphop-php)。
2.6结论
从上面分析来看,在基础的内存管理、变量、函数、运行机制方面,PHP本身并不会存在明显的性能差异,但由于PHP的动态运行特性,决定了PHP和 其他的编译型语言相比,所有的变量查找、函数运行等等都会多一些hash查找的CPU开销和额外的内存开销,至于这种开销具体有多大,可以通过后续的基准 性能和对比分析得出。
因此,也可以大体看出PHP不太适合的一些场景:大量计算性任务、大数据量的运算、内存要求很严格的应用场景。如果要实现这些功能,也建议通过扩展的方式实现,然后再提供钩子函数给PHP调用。这样可以减低内部计算的变量、函数等系列开销。
3.基准性能
对于PHP基准性能,目前缺少标准的数据。大多数同学都存在感性的认识,有人认为800QPS就是PHP的极限了。此外,对于框架的性能和框架对性能的影响很没有响应的权威数字。
本章节的目的是给出一个基准的参考性能指标,通过数据给大家一个直观的了解。
具体的基准性能有以下几个方面:
1.裸PHP性能。完成基本的功能。
2.裸框架的性能。只做最简单的路由分发,只走通核心功能。
3.标准模块的基准性能。所谓标准模块的基准性能,是指一个具有完整服务模块功能的基准性能。
3.1环境说明
测试环境:
Uname -a
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
Red Hat Enterprise Linux AS release 4 (Nahant Update 3)
8 Intel(R) Xeon(R) CPU E5520 @ 2.27GHz
软件相关:
Nginx:
nginx version: nginx/0.8.54 built by gcc 3.4.5 20051201 (Red Hat 3.4.5-2)
Php5:(采用php-fpm)
PHP 5.2.8 (cli) (built: Mar 6 2011 17:16:18)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
bingo2:
PHP框架。
其他说明:
目标机器的部署方式:脚本。
测试压力机器和目标机器独立部署。
3.2裸PHP性能
最简单的PHP脚本。
-
<?php
- require_once ‘./actions/indexAction.php’;
- $objAction = new indexAction();
- $objAction->init();
- $objAction->execute();
- ?>
- Acitons/indexAction.php里面的代码如下
- <?php
- class indexAction
- {
- public function execute()
- {
- echo ‘hello, world!’;
- }
- }
- ?>
通过压力工具测试结果如下:
3.3裸PHP框架性能
为了和3.2的对比,基于bingo2框架实现了类似的功能。代码如下
-
<?php
- require_once ‘Bingo/Controller/Front.php’;
- $objFrontController = Bingo_Controller_Front::getInstance(array(
- ‘actionDir’ => ‘./actions’,
- ));
- $objFrontController->dispatch();
压力测试结果如下:
从该测试结果可以看出:框架虽然有一定的消耗,但对整体的性能来说影响是非常小的。
3.4标准PHP模块的基准性能
所谓标准PHP模块,是指一个PHP模块所必须要具体的基本功能:
路由分发。
自动加载。
LOG初始化&Notice日志打印。所以的UI请求都一条标准的日志。
- 错误处理。
- 时间校正。
- 自动计算每个阶段耗时开销。
- 编码识别&编码转化。
- 标准配置文件的解析和调用
采用bingo2的代码自动生成工具产生标准的测试PHP模块:test。
测试结果如下:
3.5结论
从测试数据的结论来看,PHP本身的性能还是可以的。基准性能完全能够达到几千甚至上W的QPS。至于为什么在大多数的PHP模块中表现不佳,其实 这个时候更应该去找出系统的瓶颈点,而是简单的说OK,PHP不行,那我们换C来搞吧。(下一个章节,会通过一些例子来对比,采用C来处理不见得有特别的 优势)
通过基准数据,可以得出以下几个具体的结论:
1.PHP本身性能也很不错。简单功能下能够达到5000QPS,极限也能过W。
2.PHP框架本身对性能影响非常有限。尤其是在有一定业务逻辑和数据交互的情况下,几乎可以忽略。
3.一个标准的PHP模块,基准性能能够达到2000QPS(80 cpu idle)。
4.对比分析
很多时候,大家发现PHP模块性能不行的时候,就来一句“ok,我们采用C重写吧”。在公司内,采用C/C++来写业务逻辑模块的现象到处都有,在前几年甚至几乎全部都是采用C来写。那时候大家写的真是一个痛苦:调试难、敏捷不要谈。
文章出自:baidu-tech.com
![如何在 iPhone 上使用深度效果 [2023]](https://img.php.cn/upload/article/000/465/014/169410031113297.png)
如果有一件事你可以在iPhone上挑出与众不同,那就是你在处理iPhone的锁定屏幕时拥有的自定义选项的数量。在这些选项中,有深度效果功能,它使您的壁纸看起来像与锁屏时钟小部件交互。我们将解释深度效果,何时何地可以应用它,以及如何在iPhone上使用它。iPhone上的深度效果是什么?当您添加具有不同元素的墙纸时,iPhone会将其拆分为几层深度。为此,iOS利用内置的神经引擎来检测壁纸中的深度信息,将您想要出现在焦点中的主题与所选背景的其他元素分开。这将产生一种看起来很酷的效果,其中墙纸中的主

不包含任何循环或回路的图被称为非循环图。树是一种非循环图,其中每个节点都与另一个唯一节点相连。非循环图也被称为无环图。循环图与非循环图的区别-CycleGraph的中文翻译为:循环图非循环图图形形成一个闭环。图表没有形成闭环。图表中不包含深度循环图表包含每个深度。示例1让我们举一个循环图的例子−当闭环存在时,就形成了循环图。FigureI代表了循环图,不包含深度节点。Example2的翻译为:示例2让我们以一个非循环图的例子来说明:树的根节点称为零深度节点。在图II中,在零深度处只有一个根,即2

Django框架是一种用于Web应用程序的Python框架,它提供了一个简单而强大的方式来创建Web应用程序。事实上,Django已经成为当前最受欢迎的PythonWeb开发框架之一,也成为很多公司的首选,包括Instagram和Pinterest。本文将深入探讨Django框架是什么,包括基础概念和重要组件,以及具体代码示例。Django基础概念Djan

作为一个流行的PHP框架,Laravel提供了许多便捷的请求方法来处理不同类型的HTTP请求。其中,Head请求方法是一个比较特殊且常被忽视的方法。在本文中,我们将深入探讨Laravel中Head请求方法的作用、用法和示例代码。什么是Head请求方法?Head请求方法是HTTP协议中定义的一种请求方法,在发送Head请求时,服务器将仅返回请求头信息,而不会返

Go语言是一门由Google开发的编程语言,具有高效、简洁、并发性强等特点。它在语法结构、包管理、高级特性等方面都有很大的优势,因此备受程序员青睐。然而,在实际开发中,很多项目会涉及到与传统的编程语言C进行交互,因此Go语言与C语言的兼容性就显得尤为重要。首先,我们来谈谈Go语言与C语言的兼容性。在Go语言中,可以通过CGo将Go语言与C语言进行交互。CGo

Go语言作为一种现代化的编程语言,以其简洁高效的特性在近年来受到越来越多开发者的喜爱和青睐。其中一个让人独特的地方就是其单线程特性。在传统的多线程编程语言中,开发者通常需要手动管理线程之间的同步和互斥,而在Go语言中,借助其独特的协程(Goroutine)和通信机制(channel),可以方便且高效地实现并发编程。一、Goroutine与单线程:Go语言中的

Golang是一种由谷歌开发的编程语言,其出色的性能和并发特性使其在各种领域中得到了广泛的应用,包括网络编程、大数据处理等。然而,对于一些需要直接操作硬件的领域,比如驱动程序开发,人们可能会开始思考:Golang是否适合用于编写驱动程序呢?本文将深入探讨这个问题,并通过具体的代码示例来展示Golang在驱动程序开发中的应用。首先,让我们来了解一下什么是驱动程

简要介绍研究作者提出了 Matrix Net (xNet),一种用于目标检测的新深度架构。xNets将具有不同大小尺寸和纵横比的目标映射到网络层中,其中目标在层内的大小和纵横比几乎是均匀的。因此,xNets提供了一种尺寸和纵横比感知结构。研究者利用xNets增强基于关键点的目标检测。新的的架构实现了比任何其他单镜头检测器的时效性高,具有47.8的mAP在MS COCO数据集,同时使用了一半的参数而且相比于第二好框架,其在训练上快了3倍。简单结果展示上图所示,xNet的参数及效率要远远超过其它模型


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),