PHP7.4启用opcache并进行基准测试

启用

/path/to/7.4/php.ini

[opcache]

zend_extension=opcache.so

; 1.启用,默认禁用
opcache.enable=1

; 是否用于cli,同opcache.enable
opcache.enable_cli=1

; 由于我希望在php-fpm启动后,不检查文件的变化(减少没必要的资源开支),这里我设置为0;如果设置为1,那么opcache.revalidate_freq生效
opcache.validate_timestamps=0

; 注意这里我注释了,1.表示每秒检查文件变化,0表示每个请求都检查文件变化
; opcache.revalidate_freq=2

重启php-fpm:

kill -usr2 $(cat /path/to/php-fpm@7.4.pid)

使用ab命令测试效果

这是我的测试代码:

// plus.php
<?php

for($i=0, $total = 0;$i<=10000000;$i++){
    $total += $i;
}

echo $total;

ab命令如下:

ab -c 5 -n 50 'https://blog.yeskn.com/plus.php'

开启之前:

Document Path:          /plus.php
Document Length:        14 bytes

Concurrency Level:      5
Time taken for tests:   3.745 seconds
Complete requests:      50
Failed requests:        0
Total transferred:      7800 bytes
HTML transferred:       700 bytes
Requests per second:    13.35 [#/sec] (mean)
Time per request:       374.523 [ms] (mean)
Time per request:       74.905 [ms] (mean, across all concurrent requests)
Transfer rate:          2.03 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       27   34   3.9     33      43
Processing:   147  317  74.9    300     443
Waiting:      146  317  74.9    300     443
Total:        189  350  74.7    333     476

Percentage of the requests served within a certain time (ms)
  50%    333
  66%    389
  75%    418
  80%    435
  90%    469
  95%    471
  98%    476
  99%    476
 100%    476 (longest request)

开启之后:

Document Path:          /plus.php
Document Length:        14 bytes

Concurrency Level:      5
Time taken for tests:   2.467 seconds
Complete requests:      50
Failed requests:        0
Total transferred:      7800 bytes
HTML transferred:       700 bytes
Requests per second:    20.27 [#/sec] (mean)
Time per request:       246.721 [ms] (mean)
Time per request:       49.344 [ms] (mean, across all concurrent requests)
Transfer rate:          3.09 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       27   34   4.6     33      47
Processing:   102  197  52.4    188     295
Waiting:      101  197  52.4    188     295
Total:        135  231  52.2    229     327

Percentage of the requests served within a certain time (ms)
  50%    229
  66%    266
  75%    279
  80%    285
  90%    300
  95%    311
  98%    327
  99%    327
 100%    327 (longest request)

可以看到,QPS提升了大概0.5倍,并且速度提升很大,启用opcache后,最慢的请求只有327ms,没启用时,50%的请求都要大于333ms,提升效果显著。

以上测试用的是默认配置,如果进行合理的配置,我相信优化会更加明显!

编译安装PHP扩展:imagick

由于wordpress建议安装imagick,而它默认没有加入到php源码中,于是记录一下自己编译安装imagick扩展的过程:

wget https://pecl.php.net/get/imagick-3.4.4.tgz
tar -xvf imagick-3.4.4.tgz && cd imagick-3.4.4

/usr/local/opt/php@7.4/bin/phpize

# 这个目录似乎没用到
mkdir /usr/local/opt/imagick

./configure --prefix=/usr/local/opt/imagick --with-php-config=/usr/local/opt/php@7.4/bin/php-config

报错:

checking ImageMagick MagickWand API configuration program... checking Testing /usr/local/bin/MagickWand-config... Doesn't exist
checking Testing /usr/bin/MagickWand-config... Doesn't exist
checking Testing /usr/sbin/bin/MagickWand-config... Doesn't exist
checking Testing /opt/bin/MagickWand-config... Doesn't exist
checking Testing /opt/local/bin/MagickWand-config... Doesn't exist
configure: error: not found. Please provide a path to MagickWand-config or Wand-config program.

解决办法:

yum install -y ImageMagick-devel

最后:

make && make install

vi /usr/local/etc/php/7.4/php.ini

# 在最后加入:
extension=imagick.so

# 查看是否OK:
/usr/local/opt/php@7.4/bin/php -m | grep imagick

重启php-fpm生效:

systemctl restart php-fpm@7.4

编译安装PHP8.0-alpha3

后续

目前发现几个问题:

  1. --with-config-file-scan-dir选项无效,因此无法扫描到/usr/local/etc/php/8.0-alpha/conf.d中的ini文件(在centos7上尝试没有发现这个问题)
  2. 交互式运行无效,/usr/local/opt/php@8.0-alpha/bin/php -a执行后,输出Interactive mode enabled后卡住了,无法输入代码。 (通过指定--with-readline=/usr/local/opt/readline解决)

正文

我写了一系列文章记录我编译安装PHP7.3、PHP7.4的过程,这一次我尝试编译安装PHP8.0,当前PHP8.0处于测试中,请勿直接在您的线上环境使用此版本。

Continue reading "编译安装PHP8.0-alpha3"

PHP7.*新特性

PHP7.0新特性

  1. 标量类型声明

函数参数除了array,class,interface, callable,目前支持int,string,bool,float标量声明。

<?php
// Coercive mode
function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));
  1. 返回值类型声明
<?php
function func(): array {
    return [];
 }
  1. null合并运算符 ??
<?php
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
  1. 太空船操作符 <=> 比较大小返回(-1,0,1)

  2. 通过 define() 定义常量数组

  3. 匿名类

  4. 支持 yield from

  5. yield支持return,Generator::getReturn() 获取return的值

PHP7.1新特性

  1. 可为null类型声明
<?php
function testReturn(): ?string {
    return 'elePHPant';
}

function test(?string $name)
{
    var_dump($name);
}
  1. void返回类型声明
  2. 类常量可见性 private const PRIVATE_CONST = 4;
  3. 多异常捕获处理
<?php
try {
    // some code
} catch (FirstException | SecondException $e) {
    // handle first and second exceptions
}
  1. list()支持键名
foreach ($data as list("id" => $id, "name" => $name)) {
    // logic here with $id and $name
}

// [] style
foreach ($data as ["id" => $id, "name" => $name]) {
    // logic here with $id and $name
}

PHP7.2新特性

  1. object对象类型
<?php

function test(object $obj) : object
{
    return new SplQueue();
}

test(new StdClass());
  1. 允许重写抽象方法
<?php

abstract class A
{
    abstract function test(string $s);
}

abstract class B extends A
{
    // overridden - still maintaining contravariance for parameters and covariance for return
    abstract function test($s) : int;
}

PHP7.3新特性

PHP7.4新特性

  1. 属性类型声明
<?php
class User {
    public int $id;
    public string $name;
}
  1. 箭头函数
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
  1. 空合并赋值运算符
<?php
$array['key'] ??= computeDefault();
  1. 数组中间unpack
<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
  1. 数字支持_
<?php
$a = 299_792_458;   // decimal

composer 内存溢出的两种解决办法

今天执行composer update命令时,又遇到了composer的经典报错:

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 268435456 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php on line 223

索性记录一下遇到这个错误的解决办法:

办法1:增加swap内存

mkdir /var/swap && \
dd if=/dev/zero of=/var/swap/swap_1G bs=2048 count=524288 && \
chmod 0600 /var/swap/swap_1G && \
mkswap /var/swap/swap_1G && \
swapon /var/swap/swap_1G && \
echo "/var/swap/swap_1G swap swap default 0 0" >> /etc/fstab
# 检查
free --si -h

对于低配服务器,很有必要哦。

办法2:临时关闭php内存限制

php -d memory_limit=-1 /usr/local/bin/composer update

你甚至可以修改php.ini让memory_limit=-1 永久生效,但是一般不建议这么做。

Laravel 为model触发事件

有时候我们需要在数据

class DemoModel extends Model
{
    protected $table = 'tax_source';

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->adminid = auth()->user()->getAuthIdentifier();
            $model->adminname = auth()->user()->user->name;
        });
    }
}

其中,可用的事件有:

saving,saved,updating,updated,creating,created,deleting,deleted。

saving对应的函数为:\Illuminate\Database\Eloquent\Model::saving,其他的类似,参数均为:

/**
 * @prams $model Model 当前操作的model
 */
function ($model) {
}

理论上并不是一定需要在boot函数注册这些事件。