• 【PHP】php7新特性及其优化原理


    PHP7新特性

    php7.x增加的新特性介绍可以参考这里:

     https://www.runoob.com/php/php7-new-features.html

     https://php.net/manual/zh/migration70.new-features.php

    php7.x版本系列相比之前的php的版本提交性能提高了不少,下图是wordpress在不同php版本下的压力测试表现。

    这里面其中的一些主要改变是性能提高的关键,主要有以下内容。

    1.zval使用栈内存


      在zend引擎和扩展中,经常要创建php变量,其底层就是一个zval指针,之前的php版本都是通过MAKE_STD_ZVAL动态的从堆内存上分配一个zval内存。而php7直接使用栈内存,好处是少了一次内存分配。php程序中回大量创建变量,所以php7会在栈上预分配一块内存来存放这些zval,来节省大量的内存分配和管理操作。

      php5

    zval *val ; MAKE_STD_ZVAL(val)

     php7

    zval val;

    2.zend_string存储hash值,array查询不再需要重复计算hash


      数组是php比较重要的数据结构,php程序中会有大量的array关联查询,虽然hashtable查找的复杂度是O(1),但是key的值每次要转化成一个hash值,需要用一个复杂的hash函数去计算的,这样就会占用cpu时间,不过不光数组,在php底层很多地方都会用到hashtable,比如类的属性方法函数等。其实php程序运行起来大部分key的值是不变的,所以php7就保存了这些hash值下次直接使用,那么php7就为字符串单独创建了新类型叫做zend_string,除了char*指针和长度之外,增加了一个hash字段,用于保存字符串的hash值,数据键值查找不再反复需要计算hash值。为了优化数组的键值查找。

     上图代码中 zend_ulong h;就是存储hash值。

    3.hashtable桶内直接存放数据,减少了内存申请次数,顺便也提升了cache命中率和访问速度。因为指针不是连续的是分布在不同的内存页上,如果读取第一个或者第三个桶,它们的数据可能会在两个页上。


    php7之前

     

    数据存放是在上图arBuckets这个结构体上,存放了一些bucket * 指针,指针上就是对应了一些数据。php7对这些做了一些改进,如下图。

    php7

     

     php7将之前arBuckets改成了上图中的arData,而这个arData直接就是一个大块内存,这个内存上面就是一个个桶bucket,这样的好处就是每次数据就不需要动态去申请内存。

    4.zend_parse_parameters改为宏实现,性能提升15%。

    5.新增加4种opcode,call_user_function(),is_int(),is_string(),is_array(),strlen(),defined() 4个函数变为php opcode指令,速度更快。

    6.PHP7 的内核中有一个重要的变化是加入了 AST(Abstract syntax tree)抽象语法树,指代码在计算机内存的一种树状数据结构,树上的每个节点都表示源代码中的一种结构,便于计算机理解和解析。

     在 PHP5系列版本中,从 php 脚本到 opcodes 的执行的过程如下:

    1. 词法扫描分析(Lexing):将源文件转换成 token 流;

    2. 语法分析(Parsing):生成 op arrays。

     PHP7 中在语法分析阶段先生成 AST:

    1. 词法扫描分析(Lexing):将源文件转换成 token 流。

    2. 语法分析(Parsing):从 token 流生成抽象语法树。

    3. Compilation:从抽象语法树生成 op arrays。    

        这个表达式($a)['b'] = 1 就会被解析成下图这样的一棵树结构

      

    7.其他更多性能优化,如基础类型 float , int , bool等改成直接进行值拷贝。排序算法改进了,PCER with JIT , execute_data和opline使用全局寄存器,使用gdb4.8的PGO功能。

    8.php7与JIT

      最初HHVM退出一个很重要的特性就是JIT,JIT就是just in time的缩写,表示运行时候将指令转换成二进制机器码,我们知道C和C++是将源代码编译然后生成二进制机器码去执行的,而php,python等脚本语言是将源代码转换成中间指令然后在vm(虚拟机)上执行,另外java系语言他们使用的JVM引擎底层也是JIT,是将java的字节码编译成二进制的机器码去执行的。对于计算密集型的的程序,JIT可以将PHP的opcode直接转换成机器码,可以大幅度提升PHP性能。

      不过PHP7.0-final版本中不会带有JIT特性的。

      但是

      为什么php7版本没有使用JIT呢?

      是因为php官方之前有个php中间版本是带有JIT的,后来php官方开发组使用JIT测试时候发现JIT对于实际项目的性能没有太大的性能提升,所以最终放弃使用JIT方案。但后来发现密集计算性的php程序使用JIT后性能还会大幅提升。

    PHP7下载与安装

     1.第一步  下载源代码
    wget https://www.php.net/distributions/php-7.2.21.tar.bz2
    
    2.第二步 解压源代码 tar -xjvf php-7.2.21.tar.bz2
    3.第三步 进入目录 cd php-7.2.21
    4.第四步 执行configure shell脚本检测环境及配置php安装目录 比如检测php安装是否必须要有gcc 和 authconfig等工具 ./configure --prefix=/usr/local/src/php7

    出现下面提示说明上面执行成功
    Generating files configure: creating .
    /config.status creating main/internal_functions.c creating main/internal_functions_cli.c +--------------------------------------------------------------------+ | License: | | This software is subject to the PHP License, available in this | | distribution in the file LICENSE. By continuing this installation | | process, you are bound by the terms of this license agreement. | | If you do not agree with the terms of this license, you must abort | | the installation process at this point. | +--------------------------------------------------------------------+ Thank you for using PHP. 5.第五步 编译安装 make && make install

    出现下面提示说明make成功
    clicommand.inc
    directorygraphiterator.inc
    invertedregexiterator.inc
    pharcommand.inc
    phar.inc

    Build complete.
    Don't forget to run 'make test'.

    出现下面提示说明make install成功
    Installing PEAR environment:      /usr/local/src/php7/lib/php/
    [PEAR] Archive_Tar    - installed: 1.4.7
    [PEAR] Console_Getopt - installed: 1.4.2
    [PEAR] Structures_Graph- installed: 1.1.1
    [PEAR] XML_Util       - installed: 1.4.3
    [PEAR] PEAR           - installed: 1.10.9
    Wrote PEAR system config file at: /usr/local/src/php7/etc/pear.conf
    You may want to add: /usr/local/src/php7/lib/php to your php.ini include_path
    /usr/local/src/php-7.2.21/build/shtool install -c ext/phar/phar.phar /usr/local/src/php7/bin
    ln -s -f phar.phar /usr/local/src/php7/bin/phar
    Installing PDO headers:           /usr/local/src/php7/include/php/ext/pdo/

     验证php安装成功

    songguojundeMBP:php7 songguojun$ pwd
    /usr/local/src/php7
    songguojundeMBP:php7 songguojun$ ls
    bin    etc    include    lib    php    var
    songguojundeMBP:php7 songguojun$ cd bin/
    songguojundeMBP:bin songguojun$ ./php -v                    #显示php版本  下面打印出php版本说明php安装成功
    PHP 7.2.21 (cli) (built: Feb 22 2019 22:19:32) ( NTS )
    Copyright (c) 1997-2018 The PHP Group
    Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

     如果php命令找不到就添加到启动文件中

    songguojundeMBP:~ songguojun$ vim ~/.bash_profile
    alias ll='ls -alF'
    alias la='ls -A'
    export PATH="/usr/local/opt/libiconv/bin:$PATH"
    alias php=/usr/local/src/php7/bin/php

    songguojundeMBP:~ songguojun$ source ~/.bash_profil

    源码安装可能会出现的问题:

    1. 缺少libiconv提示
    checking for iconv support... yes
    checking for iconv... no
    checking for libiconv... no
    configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>
     下载libiconv库
     brew install libiconv
     
  • 相关阅读:
    第13周作业集
    软件工程结课作业
    第13次作业--邮箱的正则表达式
    第12次作业--你的生日
    第11次作业
    第10次作业
    找回感觉的练习
    第16周作业
    第15周作业
    第14周作业
  • 原文地址:https://www.cnblogs.com/songgj/p/10398076.html
Copyright © 2020-2023  润新知