PHP8.0 alpha3的jit(just in time)以及其他

这篇文章通过鸟哥的多篇博客整理而成:

  1. PHP 8新特性之JIT简介
  2. PHP8新特性之match表达式
  3. PHP 8新特性之Attributes(注解)

jit

鸟哥在他的博客中说过:

jit不是opcache的替换,而是它的加强

开启jit:

# /usr/local/etc/php/8.0-alpha/php.ini

...
zend_extension=opcache
...

[opcache]
opcache.jit=1205
opcache.jit_buffer_size=64M
; Determines if Zend OPCache is enabled
opcache.enable=1

; Determines if Zend OPCache is enabled for the CLI version of PHP
opcache.enable_cli=1

进入到PHP8.0的源码目录,其中包含用于测试的文件Zend/bench.php。

不带JIT基准测试:

➔ /usr/local/opt/php@8.0-alpha/bin/php -d opcache.jit_buffer_size=0 Zend/bench.php
simple             0.015
simplecall         0.007
simpleucall        0.008
simpleudcall       0.007
mandel             0.053
mandel2            0.078
ackermann(7)       0.027
ary(50000)         0.006
ary2(50000)        0.004
ary3(2000)         0.048
fibo(30)           0.083
hash1(50000)       0.013
hash2(500)         0.010
heapsort(20000)    0.029
matrix(20)         0.030
nestedloop(12)     0.040
sieve(30)          0.015
strcat(200000)     0.007
------------------------
Total              0.482

带jit基准测试:

➔ /usr/local/opt/php@8.0-alpha/bin/php -d opcache.jit_buffer_size=64M -d opcache.jit=1205 Zend/bench.php
simple             0.001
simplecall         0.001
simpleucall        0.001
simpleudcall       0.000
mandel             0.006
mandel2            0.008
ackermann(7)       0.011
ary(50000)         0.004
ary2(50000)        0.003
ary3(2000)         0.013
fibo(30)           0.032
hash1(50000)       0.010
hash2(500)         0.007
heapsort(20000)    0.011
matrix(20)         0.012
nestedloop(12)     0.007
sieve(30)          0.006
strcat(200000)     0.003
------------------------
Total              0.137

可见,提升效果还是非常可观的!

match表达式

如果你需要通过switch并返回一个值时,以前是这么做的:

switch ($input) {
    case "true":
        $result = 1;
    break;
    case "false":
        $result = 0;
    break;
    case "null":
        $result = NULL;
    break;
}

从PHP8 alpha2起,有了更简便的方法:

$result = match($input) {
    "true", "on" => 1,
    "false", "off" => 0,
    "null", "empty", "NaN" => NULL,
};

尤其需要注意的是,match表达式用的严格比较(===),而switch是宽松比较(==)。

由于现在match是关键字了,因此,(m|M)atch不能用于函数名、类名、namespace中了,所以升级之前最好先检查是否存在这类命名,以免报错。当然,方法还是可以用match命名的。

Attributes(注解)

这个语法,容我说一句实话,那就是非常丑!

用过doctrine-annotaion库的都知道,它可以解析函数的注释,比如:

symfony可能有这样的写法:

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="MainBundle\Repository\UserRepository")
 */
class User implements UserInterface
{
    ...
}

在这段注释中,描述了这个实体对应的数据库表名,以及对应的数据仓库类名。那doctrine-annotaion是怎么做到的呢?

其实大致如下:

$ref = new ReflectionClass("User");
$doc = $ref->getDocComment();
// 对$doc字符解析,得到@ORM\Table,@ORM\Entity的具体参数

现在,php自带解析注释,这里该注释被称为注解(annotaion),来看看语法吧:

<<
 Params("Foo", "argument"),
 See("https://xxxxxxxx/xxxx/xxx.html")
>>
function dummy($argument) {}

(是不是很丑?是就对了!)依然用的反射机制,但是不需要自己解析:

$ref = new ReflectionFunction("dummy");

var_dump($ref->getAttributes("See")[0]->getName());
var_dump($ref->getAttributes("See")[0]->getArguments());

/// output:
string(3) "See"
array(1) {
  [0]=>
  string(30) "https://xxxxxxxx/xxxx/xxx.html"
}

还可以创建一个“注解类”自定义注解字段:

<?php

<<phpAttribute>>
class MyAttribute {
     public function __construct($name, $value) {
          var_dump($name);
          var_dumP($value);
     }
}

然后使用它:

<<MyAttribute("See", "https://xxxxxxxx/xxxx/xxx.html")>>
function dummy($argument) {
}

$ref = new ReflectionFunction("dummy");

$ref->getAttributes("MyAttribute")[0]->newInstance();

这样就会根据注解中的参数自动创建一个MyAttribute类的实例。

发表评论

电子邮件地址不会被公开。 必填项已用*标注