首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

全方位解读php8.0版本优化与改进

本文根据php官方发布整理描述。 除非你一直生活在一块石头下,或者生活在过去,否则你会意识到JIT正在进入PHP 8:投票今天悄然结束,绝大多数人赞成合并到PHP8,所以,这是正式的,本文全方位解读php8.0版本优化与改进。 PHP8 官宣《PHP8首个版本 Alpha1 发布!》

php 8.0  五大更新重点

效能提升

语法扩充

弹性强类别

更加严谨

调节内套件与新增函数

性能测试图表

PHP 8.0 值得关注的改进

PHP 8.0 引入了 Just In Time (JIT) 编译器,能够进一步提高 PHP 脚本的执行速度。

PHP 8.0 合并了诸多性能优化

JSON 支持现在被视为语言的核心部分,始终可用,而不是作为可选模块。

@1.extension_loaded('json')

@2.function_exists('json_decode')

始终返回true

支持 named 参数,因为它们能够指定参数名称而不是其确切顺序。

支持类/属性/函数/方法/参数/常量的结构化元数据的属性(或在其他语言中也称为注释或修饰符)。

支持可以指示多种不同类型的联合类型,这些类型可以用作参数或函数的返回类型。

支持静态返回类型。

str_contains()函数是一种检查字符串是否包含在另一个字符串中的简便方法,而不必使用strpos等。与之相似的是新的str_starts_with()和str_ends_with()函数,这些函数很容易解释。

添加了Nullsafe运算符,作为在方法上应用空合并行为的快速简便的方法

什么是 JIT

PHP实现了一个虚拟机,一种虚拟处理器,我们称之为Zend VM。PHP将人类可读的脚本编译成虚拟机能够理解的指令(我们称之为操作码),这个执行阶段就是我们所说的“编译时”。在执行的“运行时”阶段,虚拟机(Zend VM)执行代码的指令(操作码)。

这一切工作得很好,像APC(过去)和OPCache(现在)这样的工具可以缓存代码的指令(操作码),以便“编译时”只在必须的时候发生。

首先,有一行代码解释了什么是JIT:

Just-in-time 是一种编译器策略,它接受代码的中间表示形式,并在运行时将其转换为依赖于体系结构的机器代码,以便及时执行。

在PHP中,这意味着JIT将为Zend VM生成的指令作为中间表示,并发出依赖于体系结构的机器代码,因此代码的宿主不再是ZendVM,而是CPU。

PHP JIT 运作原理

Opcache 扩展可以更快的获取 Opcodes 将其直接转到 Zend VM,则 JIT 让它们完全不使用 Zend VM 即可运行。

跳过 Zend VM 并直接被 CPU 执行。 从理论上说,性能会更好。

查看phpinfo()

JIT我们配置  php.ini

opcache.jit=1205

opcache.jit_buffer_size=64M

是否在生成机器码点时候使用AVX指令, 需要CPU支持

0: 不使用

1: 使用

####### 寄存器分配策略

0: 不使用寄存器分配

1: 局部(block)域分配

2: 全局(function)域分配

JIT触发策略

0: PHP脚本载入的时候就JIT1: 当函数第一次被执行时JIT2: 在一次运行后,JIT调用次数最多的百分之(opcache.prof_threshold * 100)的函数3: 当函数/方法执行超过N(N和opcache.jit_hot_func相关)次以后JIT4: 当函数方法的注释中含有@jit的时候对它进行JIT5: 当一个Trace执行超过N次(和opcache.jit_hot_loop, jit_hot_return等有关)以后JIT

JIT优化策略,数值越大优化力度越大:

0: 不JIT

1: 做opline之间的跳转部分的JIT

2: 内敛opcode handler调用

3: 基于类型推断做函数级别的JIT

4: 基于类型推断,过程调用图做函数级别JIT

5: 基于类型推断,过程调用图做脚本级别的JIT

关于类名调用测试php 7.4版本

class ImageService{

 private $src;

 private $image;

 private $imageinfo;

 private $percent = 0.5;

 /** 高清压缩图片

  * @param string $saveName  提供图片名(可不带扩展名,用源图扩展名)用于保存。或不提供文件名直接显示

  */

 public function compressImg($saveName='')

 {

 }}###获取类名 方法一var_dump (ImageService::class);//打印结果:string(12) "ImageService"### 获取类名方法二$obj = new ImageService();var_dump(get_class ($obj));//打印结果:string(12) "ImageService"

php8.0 版本

class ImageService{

 private $src;

 private $image;

 /** 高清压缩图片

  * @param string $saveName  提供图片名(可不带扩展名,用源图扩展名)用于保存。或不提供文件名直接显示

  */

 public function compressImg($saveName='')

 {

 }}

var_dump($imageObj::class);//打印结果:string(12) "ImageService"

构造函数可直接定义成员变量php7.4版本

## php7版本

class MaterialsDao{

  private $name;

  private $pwd;

  public function __construct($name,$pwd)

  {

      $this->name = $name;

      $this->pwd  = $pwd;

  }

}

var_dump( new MaterialsDao('admin','!$123123%$'));

//打印结果object(MaterialsDao)#1 (2) {["name":"MaterialsDao":private]=>

string(5) "admin"["pwd":"MaterialsDao":private]=>

string(10) "!$123123%$"}

php8.0版本 直接定义成员变量

## php8版本 构造函数 可直接定义成员变量

class  MaterialsPHP8Dao{

 public function __construct(private $name,private $pwd)

 {

 }}var_dump( new MaterialsPHP8Dao('admin','!$123123%$'));

//打印结果

object(MaterialsPHP8Dao)#1 (2) {

["name":"MaterialsPHP8Dao":private]=>

string(5) "admin"

["pwd":"MaterialsPHP8Dao":private]=>

string(10) "!$123123%$"}

字符串的处理1.判断字符串中是否存在某个字符

php 7.4 版本

$url = "https://www.php.net/releases/8.0/zh.php";//原来方式@1. strstr

$domain = strstr($url,'http');

echo $domain; //原来方式@2. strposif(strpos($url,'http')!==false || strpos($url,'https')!==false){

  echo "包含http或https";}else{

  echo "不包含http";}

php8.0 版本 新增str_contains函数

$url = "https://www.php.net/releases/8.0/zh.php";

if(str_contains($url,"http")){

 echo "包含http或https";

}else{

 echo "不包含http";

}

2.判断字符串是否以开头 或 以结尾

php7.4版本

$str = ":测试一下喽";

if (':' ==  substr($str, 0, 1)) {

 echo "ok";

}else{

 echo "no";

}

php8.0版本 新增 str_stars_with:开始函数 str_ends_with:结束函数

if(str_starts_with($str,":测试")){

 echo "以':测试'开头";

}else{

 echo  "否";

}

if(str_ends_with($str,"喽")){

 echo "以'喽'结束";

}else{

 echo  "否";

}

3.新的关键字:match, 这个关键字的作用跟switch有点类似。

php7.4版本 switch

switch ($input) {

 case "true":

     $result = 1;

 break;

 case "false":

     $result = 0;

 break;

 case "null":

     $result = NULL;

 break;}

php 8.0 版本 新关键词match

$result = match($input) {

     "true" => 1,

     "false" => 0,

     "null" => NULL,};###多个值$result = match($input) {

 "true", "on" => 1,

 "false", "off" => 0,

 "null", "empty", "NaN" => NULL,};

4. 串联优先级

## 串联优先级 测试

$a = 100;

$b = 200;

echo '两数之和:' . $a + $b . PHP_EOL;

// PHP7.* 执行顺序是: ('两数之和:' . $a) + $b .PHP_EOL;

## 打印输出 200

// PHP8执行顺序是: '两数之和:' . ($a + $b) . PHP_EOL;

## 打印输出 300

5. 联合类型 索引

// 参数是联合类型function paramsUnionType(array|bool $data) {

 var_dump($data);}// 参数为数组paramsUnionType(['a', 'd', 'e']);// 参数为布尔型paramsUnionType(false);// 返回值是联合类型function retUnionType($data) : array|bool|string {

 return $data;}// 返回值为数组类型var_dump(retUnionType(['b', 'a', 1]));// 返回值为布尔类型var_dump(retUnionType(true));// 返回值为字符串类型var_dump(retUnionType('new1024kb'));

// 参数和返回值都是联合类型function unionType(array|bool $data): bool|array {

 return $data;}// 数组类型var_dump(unionType(['a', 'f', 'q']));// 布尔类型var_dump(unionType(true));// 整型(会被转换成bool型 true)var_dump(unionType(127867));

6.fdiv 函数 允许除数为0

// 除数为0var_dump(fdiv(2, 0));var_dump(fdiv(1, 3));var_dump(fdiv(1, 2));// intdiv() 对结果取整// fmod() 返回余数返回结果:float(INF)float(0.3333333333333333)float(0.5)

get_debug_type和gettype()  区别

$arr = [1, 2, 3];echo '数组类型' . PHP_EOL;var_dump('get_debug_type(): '. get_debug_type($arr));var_dump('gettype(): ' . gettype($arr));$str = 'new1024kb';echo '字符串类型' . PHP_EOL;var_dump('get_debug_type(): ' . get_debug_type($str));var_dump('gettype(): ' . gettype($str));echo PHP_EOL;$i = 1024;echo '整型' . PHP_EOL;var_dump('get_debug_type(): ' . get_debug_type($i));var_dump('gettype(): ' . gettype($i));echo PHP_EOL;$str = 10.24;echo '字符串类型' . PHP_EOL;var_dump('get_debug_type(): ' . get_debug_type($str));var_dump('gettype(): ' . gettype($str));echo PHP_EOL;

$b = false;echo '布尔型' . PHP_EOL;var_dump('get_debug_type(): ' . get_debug_type($b));var_dump('gettype(): ' . gettype($b));echo PHP_EOL;

class Type{}$type = new Type();echo '对象' . PHP_EOL;var_dump('get_debug_type(): ' . get_debug_type($type));var_dump('gettype(): ' . gettype($type));

运行结果:

函数参数int型参数string型参数布尔bool型参数数组array型对象浮点型实例化-intstringboolarrayfloat实例化get_debug_typeintstringboolarrayfloat类名gettypeintegerstringbooleanarraydoubleobject7.  php8 新增参数跳过 参数与顺序无关,且是自描述的。

属性

function named_params($a, $b, $c = 0, $d = 0) {

 echo $a."-".$b."-".$c."-".$d;}echo "function: ";named_params(1, 2,d:20 );##打印结果: 1-2-0-20%

8. NULLsafe

php7.4

$country =  null;if ($session !== null) {

$user = $session->user;

if ($user !== null) {

 $address = $user->getAddress();

 if ($address !== null) {

   $country = $address->country;

 }

}}

php8.0

$country = $session?->user?->getAddress()?->country;

9. PHP 8新特性之Attributes  注释

php7.4 版本

/**

* @param $where

* @param string $field

* @return array

*/function getOne($where, $field='*'){

 return  [];}$ref = new ReflectionFunction("getOne");var_dump ( $ref->getDocComment());## 打印结果string(6) "author"array(2) {

[0]=>

string(6) "123123"

[1]=>

string(44) "https://stitcher.io/blog/attributes-in-php-8"}

php8.0

$ref01 = new ReflectionFunction("getOneById");var_dump($ref01->getAttributes("Params")[0]->getName());var_dump($ref01->getAttributes("Params")[0]->getArguments());var_dump($ref01->getAttributes("See")[0]->getName());var_dump($ref01->getAttributes("See")[0]->getArguments());string(3) "see"array(2) {

[0]=>

string(6) "123123"

[1]=>

string(44) "https://stitcher.io/blog/attributes-in-php-8"}#[Params("name", "pwd"),author("123123","https://stitcher.io/blog/attributes-in-php-8")]function getOneByName($name,$pwd){

 return boolval (1);}$ref01 = new ReflectionFunction("getOneByName");var_dump($ref01->getAttributes("Params")[0]->getName());var_dump($ref01->getAttributes("Params")[0]->getArguments());string(6) "Params"array(2) {

[0]=>

string(4) "name"

[1]=>

string(3) "pwd"}var_dump($ref01->getAttributes("author")[0]->getName());var_dump($ref01->getAttributes("author")[0]->getArguments());string(6) "author"array(2) {

[0]=>

string(6) "123123"

[1]=>

string(44) "https://stitcher.io/blog/attributes-in-php-8"}

PHP的开发速度会减慢吗?

没有理由认为会这样。我们有足够的时间可以满怀信心地说,到PHP 8普遍可用时,我们中已经有足够多的人熟悉JIT,至少在修复bug和推动PHP向前发展方面能够像今天一样发挥作用。

当试图将这一点与JIT本质上是复杂的观点联系起来时,请考虑我们花在引入新特性上的大部分时间实际上是花在讨论该特性上的。对于大多数功能,甚至修复,代码可能需要几分钟或几小时的编写时间,而讨论则需要几周或几个月的时间。在极少数情况下,一个特性的代码可能需要几个小时或几天的时间来编写,但在这些极少数情况下,讨论总是需要更长的时间。

新语法开始面向其他设计語言 PHP 开始活用强型别写发的特性 PHP 正在一步一步的要求严谨 JIT 目前在 PHP 8.0 能提升的情境有限

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201227A0E56S00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券