PHP的性能探讨和测试

PHP的性能探讨和测试,第1张

1缘起

关于PHP,很多人的直观感觉是PHP是一种灵活的脚本语言,库类丰富,使用简单,安全,非常适合WEB开发,但性能低下。PHP的性能是否真的就如同大家的感觉一样的差呢?本文就是围绕这么一个话题来进行探讨的。从源码、应用场景、基准性能、对比分析等几个方面深入分析PHP之性能问题,并通过真实的数据来说话。

2从原理分析PHP性能

从原理分析PHP的性能,主要从以下几个方面:内存管理、变量、函数、运行机制来进行分析。

21内存管理

类似Nginx的内存管理方式,PHP在内部也是基于内存池,并且引入内存池的生命周期概念。在内存池方面,PHP对PHP脚本和扩展的所有内存相关 *** 作都进行了托管。对大内存和小内存的管理采用了不同的实现方式和优化,具体可以参考以下文档:

22变量

总所周知,PHP是一种弱变量类型的语言,所以在PHP内部,所有的PHP变量都对应成一种类型Zval,其中具体定义如下:

在变量方面,PHP做了大量的优化工作,比如说Reference counting和copy on writer机制。这样能够保证内存使用上的优化,并且减少内存拷贝次数(请参考

23函数

在PHP内部,所有的PHP函数都回转化成内部的一个函数指针。比如说扩展中函数

ZEND_FUNCTION(my_function);//类似functionmy_function(){}

在内部展开后就会是一个函数

voidzif_my_function(INTERNAL_FUNCTION_PARAMETERS);

voidzif_my_function(intht,

zvalreturn_value,

zvalthis_ptr,

intreturn_value_used,

zend_executor_globalsexecutor_globals);

从这个角度来看,PHP函数在内部也是对应一个函数指针。

24运行机制

在话说PHP性能的时候,很多人都会说“C/C++是编译型,JAVA是半编译型,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是非常类似的,都是先产生中间码,然后运行在不同虚拟机上。

25动态运行

从上面的几个分析来看,PHP在内存管理、变量、函数、运行机制等几个方面都做了大量的工作,所以从原理来看,PHP不应该存在性能问题,性能至少也应该和Java比较接近。

这个时候就不得不谈PHP动态语言的特性所带来的性能问题了,由于PHP是动态运行时,所以所有的变量、函数、对象调用、作用域实现等等都是在执行阶段中才确定的。这个从根本上决定了PHP性能中很难改变的一些东西:在C/C++等能够在静态编译阶段确定的变量、函数,在PHP中需要在动态运行中确定,也就决定了PHP中间码不能直接运行而需要运行在Zend Engine上。

说到PHP变量的具体实现,又不得不说一个东西了:Hashtable。Hashtable可以说在PHP灵魂之一,在PHP内部广泛用到,包含变量符号栈、函数符号栈等等都是基于hashtable的。

以PHP变量为例来说明下PHP的动态运行特点,比如说代码:

php

$var=“hello,”;

该代码的执行结果就是在变量符号栈(是一个hashtable)中新增一个项

当要使用到该变量时候,就去变量符合栈中去查找(也就是变量调用对出了一个hash查找的过程)。

同样对于函数调用也基本上类似有一个函数符号栈(hashtable)。

其实关于动态运行的变量查找特点,在PHP的运行机制中也能看出一些。PHP代码通过解释、编译后的流程下图:

从上图可以看出,PHP代码在compile之后,产出的了类符号表、函数符号表、和OPCODE。在真正执行的时候,zend Engine会根据op code去对应的符号表中进行查找,处理。

从某种程度上,在这种问题的上,很难找到解决方案。因为这是由于PHP语言的动态特性所决定的。但是在国内外也有不少的人在寻找解决方案。因为通过这样,能够从根本上完全的优化PHP。典型的列子有facebook的hiphop。

26结论

从上面分析来看,在基础的内存管理、变量、函数、运行机制方面,PHP本身并不会存在明显的性能差异,但由于PHP的动态运行特性,决定了PHP和其他的编译型语言相比,所有的变量查找、函数运行等等都会多一些hash查找的CPU开销和额外的内存开销,至于这种开销具体有多大,可以通过后续的基准性能和对比分析得出。

因此,也可以大体看出PHP不太适合的一些场景:大量计算性任务、大数据量的运算、内存要求很严格的应用场景。如果要实现这些功能,也建议通过扩展的方式实现,然后再提供钩子函数给PHP调用。这样可以减低内部计算的变量、函数等系列开销。

3基准性能

对于PHP基准性能,目前缺少标准的数据。大多数同学都存在感性的认识,有人认为800QPS就是PHP的极限了。此外,对于框架的性能和框架对性能的影响很没有响应的权威数字。

本章节的目的是给出一个基准的参考性能指标,通过数据给大家一个直观的了解。

具体的基准性能有以下几个方面:

1裸PHP性能。完成基本的功能。

2裸框架的性能。只做最简单的路由分发,只走通核心功能。

3标准模块的基准性能。所谓标准模块的基准性能,是指一个具有完整服务模块功能的基准性能。

31环境说明

测试环境:

Uname -aPnux db-forum-test17db01baiducom 269_5-7-0-0 #1 SMP Wed Aug 12

17:35:51 CST 2009 x86_64 x86_64 x86_64 GNU/Pnux

Red Hat Enterprise Pnux AS release 4 (Nahant Update 3)

8 Intel(R) Xeon(R) CPU E5520 @ 227GHz

软件相关:

Nginx:nginx version: nginx/0854 built by gcc 345 20051201 (Red Hat 345-2)

Php5:(采用php-fpm)

PHP 528 (cP) (built: Mar 6 2011 17:16:18)

Copyright (c) 1997-2008 The PHP Group

Zend Engine v220, Copyright (c) 1998-2008 Zend Technologies

with eAccelerator v0953, Copyright (c) 2004-2006 eAccelerator, by eAccelerator

bingo2:

PHP框架。

其他说明:

目标机器的部署方式:nginx-php-fpm-php脚本。

测试压力机器和目标机器独立部署。

32裸PHP性能

最简单的PHP脚本。

php

require_once‘/actions/indexActionphp’;

$objAction=newindexAction();

$objAction-init();

$objAction-execute();

Acitons/indexActionphp里面的代码如下

php

classindexAction

{

pubPcfunctionexecute()

{

echo‘hello,world!’;

}

}

通过压力工具测试结果如下:

33裸PHP框架性能

为了和32的对比,基于bingo2框架实现了类似的功能。代码如下

php

require_once‘Bingo/Controller/Frontphp’;

$objFrontController=Bingo_Controller_Front::getInstance(array(‘actionDir’=‘/actions’,));

$objFrontController-dispatch();

压力测试结果如下:

从该测试结果可以看出:框架虽然有一定的消耗,但对整体的性能来说影响是非常小的。

34标准PHP模块的基准性能

所谓标准PHP模块,是指一个PHP模块所必须要具体的基本功能:

路由分发。

自动加载。

LOG初始化Notice日志打印。所以的UI请求都一条标准的日志。

错误处理。

时间校正。

自动计算每个阶段耗时开销。

编码识别编码转化。

标准配置文件的解析和调用

采用bingo2的代码自动生成工具产生标准的测试PHP模块:test。

测试结果如下:

35结论

从测试数据的结论来看,PHP本身的性能还是可以的。基准性能完全能够达到几千甚至上W的QPS。至于为什么在大多数的PHP模块中表现不佳,其实这个时候更应该去找出系统的瓶颈点,而是简单的说OK,PHP不行,那我们换C来搞吧。(下一个章节,会通过一些例子来对比,采用C来处理不见得有特别的优势)

通过基准数据,可以得出以下几个具体的结论:

1PHP本身性能也很不错。简单功能下能够达到5000QPS,极限也能过W。

2PHP框架本身对性能影响非常有限。尤其是在有一定业务逻辑和数据交互的情况下,几乎可以忽略。

3一个标准的PHP模块,基准性能能够达到2000QPS(80 cpu idle)。

4对比分析

很多时候,大家发现PHP模块性能不行的时候,就来一句“ok,我们采用C重写吧”。在公司内,采用C/C++来写业务逻辑模块的现象到处都有,在前几年甚至几乎全部都是采用C来写。那时候大家写的真是一个痛苦:调试难、敏捷不要谈。

1、WEB基础

要知道网站是什么东西,所使用的协议是怎么工作的,怎样把网站放在服务器上。

2、HTMLphp

HTMLphp是嵌入在HTML的语言,所以HTML是必须的。可以用HTML写出简单的静态的页面,放在本机的服务器上看看效果。

3、DIV+CSS

能够用DIV+CSS布局做出漂亮的精美静态网页。

4、php基础

学习php基础,如php语法,php变量,php流程控制,php函数,php数组应用,php字符串处理,php常用模块,php文件处理,php动态图像处理,会话控制等,就可以把静态页面变成动态的。这个阶段比较枯燥,主要是记忆,必须能够熟练应用。

5、MySQL

网站往往包含大量的信息,这些信息不可能都放在程序(php文件)中,需要MySQL来储存大量的数据信息。

6、Javascript

掌握了以上内容就可以搭建一个php基础网站,但是还需要靠Javascript来完成网站的特效和信息验证等。

7、php高级

作为一个可以上线运营的全功能网站,还要继续学习php高级知识,如php面向对象,数据抽象层PDO,MEMCACHE,高级SESSION,php的设计模式,MVC,smarty模板,主流框架的解读等内容,这个阶段需要多读优质的开源代码,多写代码。

8、Linux

正如大家所熟知的php较佳的搭配是LAMP(Linux+Apache+MySQL+Php)或LNMP(Linux+Nginx+MySQL+Php),那么显然在Linux系统下的php网站比在Windows下兼容性好,基于此我们需要知道在Linux下搭建php环境的方法以及Linux的日常管理命令,以便我们网站的日常管理运营。

9、项目相关

这个阶段首先需要了解项目开发流程,需求分析,程序设计说明书,数据库设计说明书,编码规范,大流量/大数据架构,MYSQL深度优化,全文索引等内容。

目前为止学到这个阶段,已经可以算是php小牛了,要继续向php大牛进发就需要参与开发大型网站项目,以此练手。北大青鸟认为参与大项目开发,实践为主。通过这阶段的学习就可以自主做企业网站、论坛、网页游戏等。

php需要学好什么?一起来了解一下吧。

1、前端基础知识HTML、CSS、JS等,学习完成阶段可自行制作简单的网页,熟悉元素属性。

2、理解动态语言的概念和运做机制,学好基本的PHP语法、函数。

3、将PHP与HTML结合起来的方法,能够完成简单的动态页面制作。

4、MySQL、设计数据库、数据库优化、缓存、大数据等。

5、全部PHP语法和大部分的PHP常用函数,面向对象编程,MySQL优化,以及一些模板和框架。

拓展:php工程师是什么

php工程师是对使用php语言进行web应用系统开发的人的统称,主要分为php初级工程师、php中级工程师和php高级工程师三个等级。PHP工程师能够熟练使用各种PHP函数和框架函数或对象进行系统业务逻辑开发,与前端对接等工作。

今天的分享就是这些了,希望能对你们有帮助哟!

ThinkPHP中 C(),D(),S()

1在具体的Action方法里面,可以用C()对某些参数进行动态配置,主要指那些还没有使用的参数。具体用法如下:

C('参数名称'); //获取已经设置的参数值

C('参数名称','新的参数值'); //设置新的值

2D()函数的使用:

先定义好模型类,如UserModel,然后就可以用D()函数对数据进行 *** 作了。例如:

先在"你的项目"\Lib\Model下建立一个名为UserModelclassphp的PHP脚本,内容如下:

class UserModel extends Model{}

然后,无需增加任何属性和方法,就可以进行如下 *** 作:

$User = D("User"); //实例化User对象,User是你在数据库建立的一个名为"前缀_user"的数据表

也可以用$User = new UserModel()代替,进行实例化对象的 *** 作。

实例化之后,就可以对数据进行增删查改等一系列 *** 作了,如:

$User->find(1); //查找主键为1的记录

3S()函数的使用:

ThinkPHP把各种缓存方式都抽象成统一的缓存类来调用,而且ThinkPHP把所有的缓存机制统一成一个S方法来进行 *** 作,所以在使用

不同的缓存方式的时候并不需要关注具体的缓存细节。如:

S('data',$Data); //使用data标识缓存$Data数据

S('data',$Data,3600); //缓存$Data数据3600秒

$Data = S('data'); //获取缓存数据

本文实例讲述了php常用字符串处理函数。分享给大家供大家参考。具体分析如下:

这里只提供几个简单常用的函数:

chop执行去除空格处理,get_html_translation_table返回转化列表到变量,定义包括HTML编码的字符串htmlentities,htmlspecialchars_decode

定义包含HTML特殊字符的字符串,nl2br

quotemeta

rtrim等

定义和用法:chop()

函数从字符串的末端开始删除空白字符或其他预定义字符,该函数的

rtrim()

函数的别名

语法:chop(string,charlist),代码如下:

复制代码

代码如下:$str="i'm

a

teacher

";

//定义字符串

$result=chop($str);

//执行去除空格处理

echo

$result;

//输出结果

定义和用法:get_html_translation_table()

函数返回被

htmlentities()

htmlspecialchars()

函数使用的翻译表

语法:get_html_translation_table(function,quotestyle),代码如下:

复制代码

代码如下:

$trans=get_html_translation_table(html_entities);

//返回转化列表到变量

print_r($trans);

//输出转换表

$str="hallo

&

<frau>

&

krmer";

//定义字符串

$encoded=strtr($str,$trans);

//查找字符

echo

$encoded;

//输出结果

//

$str="a

'quote'

is

<b>bold</b>";

//定义包括html编码的字符串

echo

htmlentities($str);

//输出经过处理的字符串

echo

htmlentities($str,

ent_quotes);

//加上可选参数后的输出结果

//

$str='<p>this

->

"</p>';

//定义包含html特殊字符的字符串

echo

htmlspecialchars_decode($str);

//输出转换后的内容

echo

"<br>";

echo

htmlspecialchars_decode($str,ent_noquotes);

//不对引号进行编码的输出结果

//

$str="cat

isn't

n

dog";

//定义包含换行符的字符串

$result=nl2br($str);

//执行转换 *** 作

echo

$result;

//输出转换后的结果

//

$str="hello

world(can

you

hear

me)";

//定义包含元字符的字符串

$result=quotemeta($str);

//执行转换 *** 作

echo

$result;

//输出转换后的结果

//

$str="hello

world

";

//定义末尾有空格的字符串

$result=rtrim($str);

//执行转换 *** 作

echo

$result;

//输出转换后的结果

希望本文所述对大家的php程序设计有所帮助。

exec()函数和shell_exec()函数

1、exec()函数执行外部系统命令,并将命令输出返回到一个变量中。

2、shell_exec()函数通过shell执行命令,并将命令输出返回到一个字符串中。

从这篇文章开始,我们将学习一系列的 PHP 文件系统相关函数。其实这些函数中,有很多都是我们经常用到的,大家并不需要刻意地去记住它们,只要知道有这么个东西,在使用的时候记得来查文档就可以了。

文件路径相关的函数往往在一些框架中会比较常见,而且多会配合 __FILE__ 、 __DIR__ 之类的魔术常量使用。

basename() 函数是获得路径中的文件名,它有两个参数,第一个是文件的路径,第二个是过滤掉的内容,比如第一条测试语句我们过滤掉文件的后缀名。

dirname() 返回的是路径中的路径部分,也就是不包含文件名的那部分内容,和 basename() 正好是相反的功能。

pathinfo() 函数用于以数组的形式返回路径中的信息,从结果来看,我们可以看到文件的 dirname 部分,basename 部分,以及文件的扩展名 extension 和不包含扩展名的 filename 内容。

realpath() 返回的是规范化的绝对路径名,它扩展所有的符号连接并且处理输入的路径中的 / 、 / 以及多余的 / ,返回的内容是标准规范的绝对路径。

接下来,我们学习一些修改文件相关属性的函数,主要就是在 Linux 系统环境中的文件权限信息的 *** 作。

当然,首先我们得创建一个文件。和 Linux 中的命令是非常类似的。

touch() 函数除了给出要创建的文件名之外,还有两个可选参数可以指定文件的创建时间及访问时间,不给参数的话默认就是当前时间。这个文件名可以是相对或绝对路径中有权限的目录,并在该目录下创建一个空的文件。

通过 fileowner() 函数,我们可以获得某个文件所属的用户,默认情况下我们的用户是当前运行 PHP 脚本的用户,也就是系统目前的登录用户。在这里,我们使用 chown() 函数,将用户改为 www 用户。clearstatcache() 是用于清理文件系统的缓存信息,如果不清理一下的话,fileowner() 返回的依然还是之前的用户信息。

同理,使用 filegroup() 函数获得文件的属组信息,chgrp() 用于修改文件的属组。fileperms() 用于返回文件的权限信息,它返回的是数字模式的文件访问权限,这里我们使用 sprintf() 格式化结果后获得我们常用的 Linux 系统权限格式。chmod() 函数用于修改文件的权限,它的权限参数是三个 8 进制数据组成的数字,也就是代表 Linux 系统中的 1 、2 、4 和它们的组合,所以我们需要在前面再加上一个 0 用于确保 *** 作能够正常执行。关于系统文件权限的知识大家需要认真学习 Linux 系统中相关的内容。

注意,上述函数如果在命令行中运行失败,大部分原因是没有权限,可以使用 sudo 进行测试。在 fastcgi 中运行时,就更加需要注意权限问题,仅在我们服务器可以 *** 作的目录中进行安全的文件权限修改。

stat() 函数可以获取到指定文件的所有属性信息,在这里我们可以看到文件的 uid 、 gid 、 ctime 、 mtime 等信息。

在 Linux 系统中,有软连接和硬连接的相关知识。其实软连接就像是 Windows 中的快捷方式,而硬连接相关于复制了一份数据。在 PHP 中,也为我们提供了创建软硬连接以及相关的一些 *** 作。

使用 link() 函数创建的就是一个指定文件的硬连接文件,而使用 symlink() 创建的则是一个软连接文件。相对来说,我们使用软连接的场景会更多一些。lstat() 就和 stat() 函数的功能一样,查看文件的各种属性信息,不过 lstat() 函数针对的是软硬连接文件。

同样地,我们也可以修改软硬连接的用户和用户组信息,不过它们的信息不能通过 fileowner() 或 filegroup() 查看。因为它们是连接文件,本身还是和原始文件绑定在一起的,使用 fileowner() 这类的函数查看到的依然是原始文件的信息。我们可以在系统环境中使用 ls -l 查看连接文件的用户和用户组信息是否修改成功。

今天的内容比较简单,而且修改权限的 *** 作也并不常用。不过对于系统安全来,它们还是非常有用的,比如对于上传来说,我们要预防上传可执行文件的话,就可以通过修改文件的权限来让文件无法直接运行,从而起到安全保护的作用。另外,目录路径相关的 *** 作也是一些框架的基础,几乎所有框架的入口或者说是 Composer 的入口,都会见到 dirname() 以及 basename() 之类函数的身影。

测试代码:

https://githubcom/zhangyue0503/dev-blog/blob/master/php/202010/source/6PHP中的文件系统函数(一)php

参考文档:

https://wwwphpnet/manual/zh/reffilesystemphp

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/12188958.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存