PNI在2016年10月之前支持php5系列的版本。9月份时进行升级,使其支持PHP7。
PNI是什么? 具体参考这边博文《PHP Native Interface》。PNI代码规模只有1000行左右,升级大概花费了一周时间(工作外时间),其中包含2天寻找思路、2天的代码升级,3-4天的问题排查。
这篇博客记录了一下PNI升级过程,包括自己学习PHP7扩展框架、API定义的过程,调试、压测、修复bug的过程等。
把这些东西记录下来,主要是为了总结出自己的学习方法和操作方法。写成博客后,可以更好地帮助自己反思升级过程中是否有操作不好的地方。当然其中也会有自己的成功经验。
搜索引擎搜到了几篇写,PHP7和PHP5的 zend api 不同的网文。随意浏览了一下,感觉帮助不是特别大。
自己下载了PHP7.0的源代码,编译一下,稍微看了一下 Zend的源码(主要看Zend_API、zend_list、zend_hash),少数几个ext里的扩展的源码。
看了后收获特别大, 了解了 php7扩展编写的几个特点:
升级的思路就有了。
依据发现的php7扩展代码的特点,决定以PHP5版本的PNI的代码为基础,进行升级。代码不需要做太大的变动,更不需要完全重写。
设立3个目标,并按顺序分步骤实现。 1. 升级代码,编译通过。 2. 功能验证通过。 3稳定性验证通过。
为了达到第一个目标,使编译通过,使用下面方法:
模仿其他extention,对比php7和php5扩展的框架架构代码,优先修改框架。
对比PHP7 源码中的zend_API.h、zend_list.h、zend_hash.h等。
函数多,可能会有API没有升级怎么办? 所以一遍升级代码,一边make,看着gcc的错误提示去一点一点改正代码。
达到第2个目标的方法,则多写功能验证的测试case。
达到第3个目标的方法,是做压力测试,观察内存和cpu的使用情况。
在升级过程中遇到过最大的一个问题是,pni中遇到内存泄漏,为了定位内存泄漏,花了非常多的时间。
总体上说,这次升级PNI比较顺利。
在做的过程中,思路其实并没有上面写的那么清楚,心中也只有个大概思路。在刚开始,寻找从何下手的过程中,还是走了一点弯路,浪费的时间不多。
走的最大的弯路则是,上文说的定位和解决pni内存泄漏的那个问题, 没有首先想到去观察对象或变量的引用计数的。这使pni升级的过程直接阻塞了。今后遇到内存泄漏的情况,应该首先观察zval的引用计数数目是否为0.
下面还是做各种假设,假设我会面临不同的情况(实际并不存在),我该设计什么样的思路和方法进行PNI的升级呢?
假设PHP7和PHP5扩展开发的框架和结构有大的不同,对PNI的升级,完全重写也许是好方案。
PNI的代码规模只有1000行,假设10W行规模以上,我在达到上文说的,第1个编译通过的目标,就不能直接用gcc的错误信息去定位没有升级的代码,不能用一边改代码一边查php7 zend api代码。应该把PHP7的代码都给熟悉了,再去升级代码。
假设升级代码规模大,php7的扩展框架和代码与php5也有大不同呢?学习成本和工程量将变得非常大,这种情况怎么做呢?
大规模的代码,逻辑上可以好分层和抽象。 升级代码前, 先写一个小的PHP7扩展,熟悉新的php7框架接口。
转载请注明来源,原地址保持永久更新。
博客首页:作程的技术博客
文章标题:《工程师手记-升级PNI以支持PHP7》
本文链接:https://it.zuocheng.net/upgrade-pni-to-suport-php7-zh
.