首页 > 作文

深入剖析PHP7内核源码(一)

更新时间:2023-04-07 12:59:01 阅读: 评论:0

php7 为什么这么快?

全新的zval 更节约的空间,栈上分配内存zend_string 存储字符串的hash值,数组查询的时候不需要进行hash计算在hashtable桶内直接存数据,减少了内存的申请次数,提升了cache命中率和内存访问速度zend_par_parameters改为了宏实现,性能提升5%增加opcode指令 call_ur_function,is_init/string/array,strlen,defined函数变成opcode指令,速度更快排序算法的改进

php7 架构

zend 引擎:zend引擎为php提供了基础服务,包括词法分析 语法分析 ,ast抽象语法树编译 opcodes执行,php的变量设计、内存管理、进程管理。php层:绑定了sapi层并处理与它的通信,它同时对safe_mode和open_badir的检测提供一致的控制层,将fopen()、fread()和fwrite()等用户空间的函数与文件和网络i/o联系起来。sapi:包括了cli fpm等,把接口对外接口都抽象出来,只要遵守sapi协议便可以实现一个rver。拓展:zend 引擎提供了核心能力和接口规范,在此基础上可以开发拓展

这里的拓展分为了两种,通常在php.ini中,通过extension=加载的扩展我们称为php扩展,通过zend_extension=加载的扩展我们称为zend扩展,但从源码的角度来讲,php扩展应该称为“模块”(源码中以module命名),而zend扩展称为“扩展”(源码中以extension命名)。两者最大的区别在于向引擎注册的钩子,向用户层面提供一些c实现的php函数,需要用到zend_module_entry(即作为php扩展),而需要hook到zend引擎的话,就得用到zend_extension(即作为zend扩展)。

php7执行流程

词法分析,把源代码切割成多个字符串单元(token)语法分析器把token转换成ast抽象语法树抽象语法树转换成opcodes(o洋务运动的局限性pcode指令集合)虚拟机解释执行执行opcodes(opcode是一组指令标识,对应handler处理函数)

执行实例

词法分析
上海理工大学专业
<?php echo "hello world";

切割成了4部分

<?php  => #define t_open_tag 379echo => #define t_echo 328空格 =>  #define t_whitespace 382"hello world" => #define t_constant_encapd_string 323
语法分析

单独存在的词块不能完整表达语义,还需要语法分析器,它会检查语法,匹配token,对token进行关联,组织串联后的产物就是ast.ast 分为多种类型,对应php语法,比如赋值语句,生成的抽象语法树节点是zend_ast_assign,赋值语句的左右会被作为zend_ast_assign类型节点的孩子(ast是php7才加入的,解耦了编译器和解释器).

opcodes

opcode是php执行过程中的中间代码,生成后由虚拟机执行,生成的opcode是类似下面的样子

line     op1        echo2        return

源码中对应的opcode及handler

zend_echo // handler:zend_echo_spec_const_handler 实现的功能是输出"hello world"zend_return  // handler:zend_return_spec_const_handler

php 生命周期

cli生命周期

php_modu古城姐妹le_startup:注册全局变量gpc等,加载内部拓展和外部拓展。php_request_startup:重置垃圾回收器,初始化执行器,初始化扫描器,设置超时时间等。php_execute_script
=> compile_file=> open_file_for_scanning(读取php代码内容,并使词人日立春法分析指针指向第一个位置) => zendpar(词法分析语法分析后生成ast) => init_op_array(初始化op_array) => zend_compile_top_stmt(把ast转为op_array) => pass_two(设置op_array对应的zend虚拟机handler) => 生成op_array=> zend_execute(zend虚拟机中执行op_array)
php_request_shutdown:调用所有关闭函数,调用所有析构函数,输出缓冲区内容,重置最大执行时间,关闭输出层(http头等),释放所有request的全局变量php_module_shutdown:调用module对应的flush函数,清理持久化的符号表,销毁全局变量,关闭所有拓展,关闭内存管理,关闭输出output,析构垃圾回收

fpm模式的生命周期

fpm跟cli模式不同的是,fpm是常驻内存的,所以php_module_startup只在启动进程的时候做一次初始化,对应的php_module_shutdown也只做一次。进入循环,调用fcgi_accept_request(accept) 阻塞等待,如果请求进来,则进入php_request_startup,初始化请求,同时加了锁来防止惊群效应
fcgi.c ...fcgi_lock(req->listen_socket); req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);fcgi_unlock(req->listen_socket);

引用

php7的性能优化总结 php扩展与zend扩展区别八个字的个性签名 《php7 底层设计与源码实现》 陈雷等

本文发布于:2023-04-07 12:59:00,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/76a48471208436c20835d70dcff4eea8.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:深入剖析PHP7内核源码(一).doc

本文 PDF 下载地址:深入剖析PHP7内核源码(一).pdf

标签:语法   函数   词法   初始化
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图