性能往往是衡量代码很重要的一个标准。我们日常编码中经常会用到一些魔术方法,这些PHP提供的魔术方法是否会影响我们程序的性能呢?是否需要减少魔术方法 的使用呢?本文将通过测试对比来了解魔术方法对性能的影响。

疑惑

魔术方法真的性能比较差吗?

PHP7里使用魔术方法的性能还是存在问题吗?

我们应该如何合理的使用魔术方法?

方案

面对我的疑惑,我的方案是:

统计对比使用魔术方法和不使用魔术方法脚本执行的时间差异

PHP5.6.26-1 下连续执行脚本n次

统计执行时间的平均值/最小值/最大值

PHP7.0.12-2 下连续执行脚本n次

统计执行时间的平均值/最小值/最大值

测试

__construct

首先我们先来看看构造函数__construct的实验,php脚本如下:<?php

/**

* 魔术方法性能探索

*

* 构造函数

*

* @author TIGERB

*/

require('./function.php');

if (!isset($argv[1])) {

die('error: variable is_use_magic is empty');

}

$is_use_magic = $argv[1];

/**

* 构造函数使用类名

*/

class ClassOne

{

public function classOne()

{

# code...

}

}

/**

* 构造函数使用魔术函数__construct

*/

class ClassTwo

{

public function __construct()

{

# code...

}

}

$a = getmicrotime();

if ($is_use_magic === 'no_magic') {

new ClassOne();

}else {

new ClassTwo();

}

$b = getmicrotime();

echo ($b-$a) . "\n";

PHP5.6不使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 no_magic php5 construct

// 运行数据统计脚本

sh analysis ./logs/__construct_no_magic_php5.log 10000

// 结果

avg: 34μs

max: 483μs

min: 26μs

PHP5.6使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 magic php5 construct

// 运行数据统计脚本

sh analysis ./logs/__construct_magic_php5.log 10000

// 结果

avg: 28μs

max: 896μs

min: 20μs

PHP7.0不使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 no_magic php construct

// 运行数据统计脚本

sh analysis ./logs/__construct_no_magic_php.log 10000

// 结果

avg: 19μs

max: 819μs

min: 13μs

PHP7.0使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 magic php construct

// 运行数据统计脚本

sh analysis ./logs/__construct_magic_php.log 10000

// 结果

avg: 14μs

max: 157μs

min: 10μs

通过上面的数据我们可以看出:

使用__construct作为构造函数的脚本执行的平均时间是要快于使用类名作为构造函数的,大概快5到6微秒,不论是在php5.6还是php7.0中。

__call

接着,我们来看看__call的实验,php脚本如下:<?php

/**

* 魔术方法性能探索

*

* 构造函数

*

* @author TIGERB

*/

require('./function.php');

if (!isset($argv[1])) {

die('error: variable is_use_magic is empty');

}

$is_use_magic = $argv[1];

/**

* 构造函数使用类名

*/

class ClassOne

{

public function __construct()

{

# code...

}

public function test()

{

# code...

}

}

/**

* 构造函数使用魔术函数__construct

*/

class ClassTwo

{

public function __construct()

{

# code...

}

public function __call($method, $argus)

{

# code...

}

}

$a = getmicrotime();

if ($is_use_magic === 'no_magic') {

$instance = new ClassOne();

$instance->test();

}else {

$instance = new ClassTwo();

$instance->test();

}

$b = getmicrotime();

echo ($b-$a) . "\n";

PHP5.6不使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 no_magic php5 call

// 运行数据统计脚本

sh analysis ./logs/__call_no_magic_php5.log 10000

// 结果

avg: 27μs

max: 206μs

min: 20μs

PHP5.6使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 magic php5 call

// 运行数据统计脚本

sh analysis ./logs/__call_magic_php5.log 10000

// 结果

avg: 29μs

max: 392μs

min: 22μs

PHP7.0不使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 no_magic php call

// 运行数据统计脚本

sh analysis ./logs/__call_no_magic_php.log 10000

// 结果

avg: 16μs

max: 256μs

min: 10μs

PHP7.0使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 magic php call

// 运行数据统计脚本

sh analysis ./logs/__call_magic_php.log 10000

// 结果

avg: 18μs

max: 2459μs

min: 11μs

通过上面的数据我们可以看出:

使用__call的脚本执行的平均时间是要慢于不使用,大概慢2微秒,不论是在php5.6还是php7.0中。

__callStatic

接着,我们来看看__callStatic的实验,php脚本如下:<?php

/**

* 魔术方法性能探索

*

* 静态重载函数

*

* @author TIGERB

*/

require('./function.php');

if (!isset($argv[1])) {

die('error: variable is_use_magic is empty');

}

$is_use_magic = $argv[1];

/**

* 存在test静态方法

*/

class ClassOne

{

public function __construct()

{

# code...

}

public static function test()

{

# code...

}

}

/**

* 使用重载实现test

*/

class ClassTwo

{

public function __construct()

{

# code...

}

public static function __callStatic($method, $argus)

{

# code...

}

}

$a = getmicrotime();

if ($is_use_magic === 'no_magic') {

ClassOne::test();

}else {

ClassTwo::test();

}

$b = getmicrotime();

echo ($b-$a) . "\n";

PHP5.6不使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 no_magic php5 callStatic

// 运行数据统计脚本

sh analysis ./logs/__callStatic_no_magic_php5.log 10000

// 结果

avg: 25μs

max: 129μs

min: 19μs

PHP5.6使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 magic php5 callStatic

// 运行数据统计脚本

sh analysis ./logs/__callStatic_magic_php5.log 10000

// 结果

avg: 28μs

max: 580μs

min: 20μs

PHP7.0不使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 no_magic php callStatic

// 运行数据统计脚本

sh analysis ./logs/__callStatic_no_magic_php.log 10000

// 结果

avg: 14μs

max: 130μs

min: 9μs

PHP7.0使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 magic php callStatic

// 运行数据统计脚本

sh analysis ./logs/__callStatic_magic_php.log 10000

// 结果

avg: 14μs

max: 159μs

min: 10μs

通过上面的数据我们可以看出:

在php5.6中使用__callStatic的脚本执行的平均时间是要慢于不使用,大概慢3微秒;在php7.0中使用__callStatic的脚本执行的平均时间是要大致等于不使用__callStatic的;

__set

接着,我们来看看__set的实验,php脚本如下:<?php

/**

* 魔术方法性能探索

*

* 设置私有属性__set

*

* @author TIGERB

*/

require('./function.php');

if (!isset($argv[1])) {

die('error: variable is_use_magic is empty');

}

$is_use_magic = $argv[1];

/**

* 实现公共方法设置私有属性

*/

class ClassOne

{

/**

* 私有属性

*

* @var string

*/

private $someVariable = 'private';

public function __construct()

{

# code...

}

public function setSomeVariable($value = '')

{

$this->someVariable = $value;

}

}

/**

* 使用_set设置私有属性

*/

class ClassTwo

{

/**

* 私有属性

*

* @var string

*/

private $someVariable = 'private';

public function __construct()

{

# code...

}

public function __set($name = '', $value = '')

{

$this->$name = $value;

}

}

$a = getmicrotime();

if ($is_use_magic === 'no_magic') {

$instance = new ClassOne();

$instance->setSomeVariable('public');

}else {

$instance = new ClassTwo();

$instance->someVariable = 'public';

}

$b = getmicrotime();

echo ($b-$a) . "\n";

PHP5.6不使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 no_magic php5 set

// 运行数据统计脚本

sh analysis ./logs/__set_no_magic_php5.log 10000

// 结果

avg: 31μs

max: 110μs

min: 24μs

PHP5.6使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 magic php5 set

// 运行数据统计脚本

sh analysis ./logs/__set_magic_php5.log 10000

// 结果

avg: 33μs

max: 138μs

min: 25μs

PHP7.0不使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 no_magic php set

// 运行数据统计脚本

sh analysis ./logs/__set_no_magic_php.log 10000

// 结果

avg: 15μs

max: 441μs

min: 11μs

PHP7.0使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 magic php set

// 运行数据统计脚本

sh analysis ./logs/__set_magic_php.log 10000

// 结果

avg: 17μs

max: 120μs

min: 11μs

通过上面的数据我们可以看出:

使用__set的脚本执行的平均时间是要慢于不使用,大概慢2微秒,不论是在php5.6还是php7.0中。

__get

接着,我们来看看__get的实验,php脚本如下:<?php

/**

* 魔术方法性能探索

*

* 读取私有属性__get

*

* @author TIGERB

*/

require('./function.php');

if (!isset($argv[1])) {

die('error: variable is_use_magic is empty');

}

$is_use_magic = $argv[1];

/**

* 实现公共方法获取私有属性

*/

class ClassOne

{

/**

* 私有属性

*

* @var string

*/

private $someVariable = 'private';

public function __construct()

{

# code...

}

public function getSomeVariable()

{

return $this->someVariable;

}

}

/**

* 使用_get获取私有属性

*/

class ClassTwo

{

/**

* 私有属性

*

* @var string

*/

private $someVariable = 'private';

public function __construct()

{

# code...

}

public function __get($name = '')

{

return $this->$name;

}

}

$a = getmicrotime();

if ($is_use_magic === 'no_magic') {

$instance = new ClassOne();

$instance->getSomeVariable();

}else {

$instance = new ClassTwo();

$instance->someVariable;

}

$b = getmicrotime();

echo ($b-$a) . "\n";

PHP5.6不使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 no_magic php5 get

// 运行数据统计脚本

sh analysis ./logs/__get_no_magic_php5.log 10000

// 结果

avg: 28μs

max: 590μs

min: 20μs

PHP5.6使用魔术方法数据如下,单位微秒μs// PHP5.6中连续调用脚本10000次

sh test 10000 magic php5 get

// 运行数据统计脚本

sh analysis ./logs/__get_magic_php5.log 10000

// 结果

avg: 28μs

max: 211μs

min: 22μs

PHP7.0不使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 no_magic php get

// 运行数据统计脚本

sh analysis ./logs/__get_no_magic_php.log 10000

// 结果

avg: 16μs

max: 295μs

min: 10μs

PHP7.0使用魔术方法数据如下,单位微秒μs// PHP7.0中连续调用脚本10000次

sh test 10000 magic php get

// 运行数据统计脚本

sh analysis ./logs/__get_magic_php.log 10000

// 结果

avg: 19μs

max: 525μs

min: 12μs

通过上面的数据我们可以看出:

在php5.6中使用__get的脚本执行的平均时间是要大致等于不使用__get的;在php7.0中使用__get的脚本执行的平均时间是要慢于不使用,大概慢3微秒。

结语

这里主要测试了__construct(), __call(), __callStatic(), __get(), __set()这五个常用的且可有其他实现方式代替的魔法函数。通过上面的测试再回来解答我的疑惑

魔术方法真的性能比较差吗?

答:除了使用__construct之外,这里使用其他的魔法方法的时间大致慢10微秒以内。

PHP7里使用魔术方法的性能还是存在问题吗?

答:在PHP7中使用与不使用魔术方法之间的差异和在PHP5.6中近乎一致。

我们应该如何合理的使用魔术方法?

答:通过整个测试我们可以看出使不使用魔法方法这之间的执行时间差异大致都是在10微秒以内的,所以如果魔法方法可以很好的节省我们的开发成本和优化我们的代码结构,我们应该可以考虑牺牲掉这不到10微秒。而__construct是要快的,所以使用__construct应该没什么异议。

php魔术方法 效率,PHP常用魔术方法的性能探究相关推荐

  1. php 魔术方法__get,php常用魔术方法

    1.构造函数__construct()和析构函数__desctruct()分别在对象创建和销毁时被调用.对象被"销毁"是指不存在任何对该对象的引用,比如引用该对象的变量被删除(un ...

  2. python魔术方法是什么_Python常用魔术方法

    什么是魔术方法? 在Python中,所有以双下划线__包起来的方法,统称为Magic Method(魔术方法),它是一种的特殊方法,普通方法需要调用,而魔术方法不需要调用就可以自动执行. 魔术方法在类 ...

  3. invoke 魔术_PHP常用魔术方法(__invoke魔术方法)

    PHP5.3魔术方法 __invoke 这个魔幻方法被调用的时机是: 当一个对象当做函数调用的时候, 如果对象定义了__invoke魔幻方法则这个函数会被调用, class Callme { publ ...

  4. Day20 python__new__、单态模式、析构方法、常用魔术方法、__str__、__repr__、__bool__ 、__len__...

    1.魔术方法 __new__ ''' 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值:通常 ...

  5. python描述符魔术方法_Python类型转换的魔术方法详解

    本文讨论python中将某个复杂对象转换为简单对象或数据类型的常用魔术放啊,这些在编程中是十分有用的. 1.__str__方法. 在讲解本方法前我们先打开一个jupyter notebook,随意创建 ...

  6. php魔术方法的理解,php魔术方法的认识

    在php中将所有以"__"即两个下划线开头的类方法保留为魔术方法,PHP中魔术方法有"__construct()"."__destruct()&quo ...

  7. python魔术方法print_Python中的魔术方法入门

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",中文称『魔术方法』,例如类的初始化方法 __init__ ,P ...

  8. php _set魔术方法的用法,PHP魔术方法__GET、__SET使用实例

    这篇文章主要介绍了PHP魔术方法__GET.__SET使用实例,本文在代码中做了详细的注释,需要的朋友可以参考下 __get() - 读取不可访问属性的值时,__get() 会被调用. __set() ...

  9. 魔术轮胎,dugoff轮胎建模 采用模块化建模方法,搭建非线性魔术轮胎PAC2002,dugoff模型

    魔术轮胎,dugoff轮胎建模 软件使用:Matlab/Simulink 适用场景:采用模块化建模方法,搭建非线性魔术轮胎PAC2002,dugoff模型. 非线性轮胎模型输入: 轮胎侧偏角,轮胎滑移 ...

最新文章

  1. apache 源代码安装
  2. 范成法加工matlab_光学非球面技术原理与加工技术
  3. SD VC - 变式价格
  4. 我犯了一个错误,您能指出吗?
  5. python for CFD(前两步问题总结)
  6. Android获取程序路径 (/data/data/appname)
  7. 求序列最长不下降子序列_最长不下降子序列nlogn算法详解
  8. Mysql多表关联删除操作
  9. 09-解决服务器被黑上不了网的问题
  10. 用delphi操作excel
  11. Python入门经典学习1-乳腺癌分类问题
  12. java 不同时区时间转换_Java中的时区转换小结
  13. HTC官方通用解锁教程(附一键解锁工具)
  14. MS4200 PCI串口卡驱动
  15. 2012年度总结:内心宁静的2012
  16. 如何解决Harbor的502问题
  17. 计算机主板芯片组型号有哪些,如何鉴别主板芯片组型号
  18. ant design pro v5 之 ProForm自定义表单项
  19. 《窈窕绅士》里的诗句
  20. spring中AOP(面向切面编程)

热门文章

  1. 一步一步学python爬虫_初学Python之爬虫的简单入门
  2. 世界第一位计算机程序员竟是女的!拜伦之女传奇一生
  3. 《自然》公布2020科学界十大人物,李兰娟、张永振入选
  4. GCN图卷积网络入门详解
  5. SCI期刊拒稿看看什么原因?
  6. 假如不穿宇航服,人在各大星球能活多久?
  7. 我国博士不是太多了,而是太少了!
  8. nginx缓存HtmL文件,Nginx在缓存的html文件上返回404
  9. 费尔马小定理素数java_利用费马小定理判断素数
  10. 【Numpy】array操作总结