PHP作为Web开发中应用最广泛的开源脚本语言,凭借库类丰富,使用简单,安全等特点,成为Facebook和BAT等互联网巨头和全球超过70%网站的主要开发语言,然而性能问题是PHP一直以来饱受诟病的,来自PHP/PECL开发组的高驰涛同学将为我们带来他对PHP性能优化方面的思考和建议。 

本期主讲:高驰涛,Neeke Gao,PHP/PECL开发组成员,同时是SeasLog,JsonNet-PHP的作者,目前在云智慧担任架构师。

今天主要从PHP的发展和性能优化历史,来谈PHP语言在性能优化方面所做过的努力,以及我们的一些研究成果。

谈起PHP,我们先来了解几个数字: 

1995年, PHP发布了第一个版本,这要感谢PHP之父Rasmus Lerdorf的辛苦努力。PHP在问世之初是Personal Home Page的缩写,那时候只是被当作制作个人网页的一门简单语言;后来随着互联网的发展以及开源社区的贡献,PHP逐步成长成为一门被广泛应用的高级语言,其英文含义也进化为PHP: Hypertext Preprocessor,即超级文本预处理语言。

官方统计数字显示,全球排名前1000万的网站应用中,有81.9%是使用PHP语言开发的。而且,每天有416个新增PHP网站进入全球前1000万排名,数量还在不断增加。发展到今天,PHP经历了4,5,7几个非常重大的版本迭代,最新的release版本是7.0.6。在二十多年的发展过程中,应用最广泛的PHP版本是PHP 5,同时也是目前全球互联网上应用最为广泛的一个语言版本。

为什么没有PHP6,而是直接从PHP5到PHP7,这里面有一个小故事。目前的PHP5.6,其实就是原预计发布的PHP6,但由于各项改动不足以支撑一个全新的PHP分支,组织内投票没有通过发布,而最终作为了PHP5.6进行发布。

PHP7又称为PHP NG,即“PHP Next Generation(下一代PHP)”,在性能和稳定性方面做了非常大的提升。为什么这么说呢,要从PHP的业务模型说起。

1、PHP Transaction Module业务模型 下面我先带大家过一下PHP5几个重大版本改动中的性能优化点,下面这张图是PHP整个运行过程中的几个关键点。

在PHP运行过程中,在Script Entry接收到请求之后。

首先经过语法解析器(Parser),此时会抛出一些致命的语法错误或警告(后续的版本改动中,会有一些致命错误转换为exception抛出);

其次经过编译器(Compiler),这部分内容中会进行更高级的解析,并测试将PHP高级语言编译成OpCode;

然后交给Execute进行执行;执行过程中发现有新的文件或类被引入,会再进行Compiler,往复执行。

从这里可以看出,其实PHP也是“编译型”语言,只不过是每次请求都编译,或称动态编译。那么,后续的优化过程中就可以进行针对性优化,即:将编译后的内容缓存起来,直接执行,以节省编译时间。

了解一点PHP的同学都知道,PHP通常被认为是简单、低效,这并不是没有道理。我们来看一段PHP源码,从而向大家解释为什么“简单”,为什么“低效”。

这段结构是PHP5及以前版本中所有变量和方法执行的核心,这是通用的变量存储结构。可以看到,同一个变量能够同时有多个属性,或long,或double,或char,或int,或array,或Object。这给工程师以充分的自由度,同样的一个数字,或字符串,不需要预设类型,就可以直接生成并使用。这就是为什么“简单”,这是对工程师来说的。

而同时丢给Zend引擎(解析执行引擎)的,有着大量的负担,因为需要引擎在每一次使用或运算时,都要不停的判断类型究竟是什么类型属性。这就是为什么“低效”的一个最直接原因。

2、PHP Performance Difficulty 性能之坑 对于一个使用PHP开发的应用来说,经过大量的实践,可以总结出4个最影响性能的点:

IO, Memory, CPU, NetWork,是不是非常眼熟?没错,这其实并不单单是PHP语言的性能瓶颈,任何一门语言,或者就目前我们所处的世界中,凡是使用计算机语言开发的服务或应用,都存在这4个瓶颈。

3、Optimize from PHP5 to PHP7 优化之旅 下面就为大家介绍一下PHP5围绕以上4个点所做的一些性能优化。在聊具体的性能优化方法之前,我们可以抛开之前的知识储备,打开脑洞,发散思维,思考应该如何入手。每个人的想法完全不一样,我的想法是这样的:

会不会是PHP本身的运行模型(或业务模型)或者Zend引擎设计存在问题? 有没有可能将PHP语言在发布运行之前进行预编译,把它转变成Bytecode? 有没有可能通过一种解析器把PHP转变成C或C++语言,然后进行make或build? 能不能开发另一套解析运行引擎? 会不会出现另一套完全不一样的运行模型(或业务模型)? 等等。

这些想法在PHP社区内屡见不鲜,并不仅仅是我一个人在这么想,非常多PHP资深专家也在思考,而且在各个方向上都有一些开源的工具或服务发布了。由于PHP5有非常多版本,这里我们仅就应用最广的PHP5.4和PHP5.5-5.6版本来简要说明性能优化的几个点。

PHP5.4 最主要的性能改进是在数组的生成和应用上面,一个简单的延后分配节省了非常大量的内存,因为多数情况数组在直接引用上并不进行运算,从而并不进行内存建立与分配工作。另外,PHP5.4在运行时中添加了Literal Table和Binding Cache操作,这两个改动相对上面延后分配内存是更复杂一些的,它在运行过程中节省了大量的CPU运算。

PHP5.5及5.6放在一起来说,因为它们真的很像,而且在目前PHP5整个大分支的维护过程中,一般是在PHP5.5上进行,然后把相关修改向5.6同步。5.5和5.6最重要的一个性能改进,是使用了编译Cache。前面我们了解了PHP的运行过程中会存在“编译->OpCode->执行”的过程,而将编译结果缓存起来是一个重要的性能优化点,OpCache就是做这个工作的。OpCache从此进入了PHP的内核,而不再是一个第三方扩展。

同时Zend引擎还有同样一个Cache优化扩展版本产生,即Zend O+,可以认为是Zend的Plus版本,在内存和CPU上,都做了一些改进。

最后来看看PHP7的几个优化点:PHP7直接修改了Zend Zval结构,这算得上是一个很大改动。同时在PHP7中,数组的结构也变得更加的不一样,这又是一个伤筋动骨的改动。官方数据中PHP7较PHP5.6有近两倍的性能提升,主要就集中在这两个点上。

看一下PHP源码:

在一个Zval结构中,一个变量仍然可以属于各种类型的,但在使用的时候,可以快速判断是哪种类型,因为不同的类型会存储在不同的指针中;而且内存使用也由于不同的指针类型而大量地降低;由于内存使用大量降低,从而为CPU更快地寻址和操作带来了更好的可能性。所以有了Zval的结构变动带来35%性能提升的结论。

同一个数组,在PHP5中的内存使用是跳跃不连贯的,而在PHP7中是连续有序的,这使得内存使用和CPU使用都更加地高效,数组的结构变动,给PHP7带来了接近50%的性能提升。

4、PHP Performance Tools 工具推荐 前面在我们发散思维时列举了很多PHP性能优化的点,几个开源社区中已经发布过针对这些的优化工具,给大家推荐一些:

Facebook发布的HHVM:

HHVM (HipHop Virtual Machine)类似于C#的CLR和Java的JVM,会将PHP代码转换成高级别的字节码(通常称为中间语言),然后在运行时通过即时(JIT)编译器将这些字节码转换为x64的机器码。 下面是一些在开发调试过程中经常使用的工具和软件服务:

此类开发工具和服务很多,可以为开发者和运维同学节省大量的定位和解决问题时间。

以我开发的SeasLog为例,由于使用内存buffer/批量IO,替代直接IO,可以直接为服务的QPS能力提升带来强劲动力,下图是SeasLog和log4php的性能对比:

最后为东家打个小广告,云智慧的APM应用性能管理产品透视宝www.toushibao.com,可以提供更为强劲的性能管理分析的商业支持方案,目前支持包括PHP,Java,DotNet,Python,IOS,Android在内各种主流应用的性能监测和管理分析能力,欢迎大家交流体验。

转载于:https://my.oschina.net/cloudwise/blog/699878

如何让PHP性能问题不再饱受诟病相关推荐

  1. 搞懂性能指标专业术语,性能面试不再懵圈

    1.性能测试分类 性能测试: 使用自动化工具,模拟不同的场景,对软件各项性能指标进行测试和评估的过程.包含负载和压力测试 负载测试: 系统在不同负载下的表现,通过该项测试可以寻求到系统在不同负载下的性 ...

  2. 如何提高VS2010的性能,VS2010不再…

    教大家几个技巧可以稍微让你觉得它没那么卡!! 一.VS2010选项视觉体验设置  工具->选项->环境  视觉体验的勾选都去掉.不解释,你懂得.(不过还是建议打开硬件加速) 二.禁用Int ...

  3. pika集群水平扩展——让性能容量不再受限

    女主宣言 Pika是一个可持久化的大容量redis存储服务,兼容string.hash.list.zset.set的绝大部分接口(兼容详情),解决redis由于存储数据量巨大而导致内存不够用的容量瓶颈 ...

  4. 《应用程序性能测试的艺术(第2版)》—第1章 1.1节从终端用户角度看性能

    本节书摘来自异步社区<应用程序性能测试的艺术(第2版)>一书中的第1章,第1.1节从终端用户角度看性能,作者[新西兰]Ian Molyneaux(莫得尼克斯),更多章节内容可以访问云栖社区 ...

  5. Java JUC 简介

    引言 本系列文章旨在介绍 Java 并发相关的知识,本文作为开篇主要介绍了 JDK 中常用的并发库(JUC)的使用方式, 后续的文章中我会自上而下地剖析了 JUC 中各个部门的实现原理,从直接下级框架 ...

  6. Goroutine 并发调度模型深度解析之手撸一个高性能 goroutine 池

    文章目录 1 前言 2 Goroutine & Scheduler 2.1 线程那些事儿 2.1.1 用户级线程模型 2.1.2 内核级线程模型 2.1.3 两级线程模型 2.2 G-P-M ...

  7. Goroutine并发调度模型深度解析之手撸一个协程池

    Goroutine & Scheduler Goroutine,Go语言基于并发(并行)编程给出的自家的解决方案.goroutine是什么?通常goroutine会被当做coroutine(协 ...

  8. JS面试八股文知识总结(最新)

    文章目录 一.JS数据类型 二.判断数据类型的方法 三.new操作符具体做了什么? 三.dom.onclick 和 dom.addEventListener的区别? 四.JS内置属性和方法 五.逻辑与 ...

  9. JavaScript高级程序设计第六章---集合引用类型

    第六章-集合引用类型 本章内容: 对象 数组与定型数组 Map.WeakMap.Set 以及WeakSet 类型 6.1 Object 显式地创建Object 的实例有两种方式: 使用new 操作符和 ...

  10. go中的G.M.P以及Goroutine、Scheduler

    go中的G.M.P以及Goroutine.Scheduler 并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代 ...

最新文章

  1. 数据分析工具Pandas(2):Pandas的索引操作
  2. linux的变量用法
  3. 网络推广外包运营浅析美的成立科技公司旨在依靠科技创新实现突破
  4. 初识Vue,写的一些小练习
  5. IDEA中Maven项目使用Junit4单元测试的写法
  6. P2571 [SCOI2010]传送带
  7. 武汉市江岸区2021年高考成绩查询,2021年武汉各区一、二、三批次高中有哪些(名单)...
  8. java spring获取bean_普通Java类获取Spring的Bean的方法
  9. JavaScript 模块化编程(二):AMD规范
  10. Javascript 中的false、0、null、undefined和空字符串对象
  11. 多图详解freeBSD8.2安装过程
  12. JavaWeb之路径问题
  13. Linux快速入门教程
  14. Composing builds 依赖统一管理实践
  15. 使用Fragment实现Tab效果
  16. 微信公众平台有哪些营销互动活动呢?
  17. TBC法师raid用饰品
  18. 异步电动机的三种仿真方式
  19. 将复制文件ExtremeCopy整合到TC(Total commander)中
  20. INTEL(英特尔)的发展历史-----

热门文章

  1. UltraLAB台式图形工作站(独门绝技~多核+超高频~极速计算工作站H490介绍)
  2. 计算机系统相机怎么卸载,如何卸载摄像头驱动
  3. 《鬼武者3》全攻略宝典
  4. 资本为什么爱“吃面”?
  5. 微信小程序图片设置成圆形
  6. 透明网桥对数据帧的处理方式
  7. 「案例」让房东在 Airbnb 上展示他们的热情好客
  8. 微信小程序 会议室课堂考勤签到助手 源码
  9. 解决microsoft store需要联网 你似乎没有联网
  10. i18n 支持参数的写法