PHP魔法函数性能分析
前言
曾經(jīng)記得鳥哥Laruence提過不建議使用"魔術(shù)方法",自此之后一旦涉及使用魔術(shù)方法的地方,我都會(huì)下意識(shí)的想一下,這樣寫真的好嗎?由于這一到兩年來一直忙于工作和學(xué)習(xí)新的知識(shí),所以在這道坎兒上一直沒有做深入的探索一直恍恍惚惚過去了,今年是我進(jìn)行深入學(xué)習(xí)的一年,因此現(xiàn)在必須對(duì)這個(gè)問題做個(gè)了結(jié)了。我們先來看看鳥哥Laruence博客曾經(jīng)提到的:
當(dāng)我把PPT分享給公司的同事的時(shí)候, 會(huì)有人質(zhì)疑, 魔術(shù)方法都不讓用?優(yōu)化的建議, 是建議, 是防止大家濫用, 肆無忌憚的用. 如果你能在寫代碼的時(shí)候, 能意識(shí)到, 什么慢, 什么快, 從而避免一些沒有必要的對(duì)魔術(shù)方法的調(diào)用, 那就是這個(gè)優(yōu)化建議所追求的效果了
疑惑
方案
面對(duì)我的疑惑,我的方案是:
- 統(tǒng)計(jì)對(duì)比使用魔術(shù)方法和不使用魔術(shù)方法腳本執(zhí)行的時(shí)間差異
- PHP5.6.26-1 下連續(xù)執(zhí)行腳本n次
- 統(tǒng)計(jì)執(zhí)行時(shí)間的平均值/最小值/最大值
- PHP7.0.12-2 下連續(xù)執(zhí)行腳本n次
- 統(tǒng)計(jì)執(zhí)行時(shí)間的平均值/最小值/最大值
目前個(gè)人能力有限,只能通過這種方式,如果你有更好的方案或者建議可以告訴我,謝謝,haha~
測(cè)試
__construct
首先我們先來看看構(gòu)造函數(shù)__construct的實(shí)驗(yàn),php腳本如下:
<?php
/**
* 魔術(shù)方法性能探索
*
* 構(gòu)造函數(shù)
*
* @author TIGERB <https://github.com/TIGERB>
*/
require('./function.php');
if (!isset($argv[1])) {
die('error: variable is_use_magic is empty');
}
$is_use_magic = $argv[1];
/**
* 構(gòu)造函數(shù)使用類名
*/
class ClassOne
{
public function classOne()
{
# code...
}
}
/**
* 構(gòu)造函數(shù)使用魔術(shù)函數(shù)__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不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php5 construct
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__construct_no_magic_php5.log 10000
// 結(jié)果
avg: 34μm
max: 483μm
min: 26μm
- PHP5.6使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php5 construct
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__construct_magic_php5.log 10000
// 結(jié)果
avg: 28μm
max: 896μm
min: 20μm
- PHP7.0不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php construct
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__construct_no_magic_php.log 10000
// 結(jié)果
avg: 19μm
max: 819μm
min: 13μm
- PHP7.0使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php construct
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__construct_magic_php.log 10000
// 結(jié)果
avg: 14μm
max: 157μm
min: 10μm
通過上面的數(shù)據(jù)我們可以看出:
使用__construct作為構(gòu)造函數(shù)的腳本執(zhí)行的平均時(shí)間是要快于使用類名作為構(gòu)造函數(shù)的,__大概快5到6微秒__,不論是在php5.6還是php7.0中。__call
接著,我們來看看__call的實(shí)驗(yàn),php腳本如下:
<?php
/**
* 魔術(shù)方法性能探索
*
* 構(gòu)造函數(shù)
*
* @author TIGERB <https://github.com/TIGERB>
*/
require('./function.php');
if (!isset($argv[1])) {
die('error: variable is_use_magic is empty');
}
$is_use_magic = $argv[1];
/**
* 構(gòu)造函數(shù)使用類名
*/
class ClassOne
{
public function __construct()
{
# code...
}
public function test()
{
# code...
}
}
/**
* 構(gòu)造函數(shù)使用魔術(shù)函數(shù)__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不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php5 call
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__call_no_magic_php5.log 10000
// 結(jié)果
avg: 27μm
max: 206μm
min: 20μm
- PHP5.6使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php5 call
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__call_magic_php5.log 10000
// 結(jié)果
avg: 29μm
max: 392μm
min: 22μm
- PHP7.0不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php call
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__call_no_magic_php.log 10000
// 結(jié)果
avg: 16μm
max: 256μm
min: 10μm
- PHP7.0使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php call
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__call_magic_php.log 10000
// 結(jié)果
avg: 18μm
max: 2459μm
min: 11μm
通過上面的數(shù)據(jù)我們可以看出:
使用__call的腳本執(zhí)行的平均時(shí)間是要慢于不使用,__大概慢2微秒__,不論是在php5.6還是php7.0中。__callStatic
接著,我們來看看__callStatic的實(shí)驗(yàn),php腳本如下:
<?php
/**
* 魔術(shù)方法性能探索
*
* 靜態(tài)重載函數(shù)
*
* @author TIGERB <https://github.com/TIGERB>
*/
require('./function.php');
if (!isset($argv[1])) {
die('error: variable is_use_magic is empty');
}
$is_use_magic = $argv[1];
/**
* 存在test靜態(tài)方法
*/
class ClassOne
{
public function __construct()
{
# code...
}
public static function test()
{
# code...
}
}
/**
* 使用重載實(shí)現(xiàn)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不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php5 callStatic
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__callStatic_no_magic_php5.log 10000
// 結(jié)果
avg: 25μm
max: 129μm
min: 19μm
- PHP5.6使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php5 callStatic
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__callStatic_magic_php5.log 10000
// 結(jié)果
avg: 28μm
max: 580μm
min: 20μm
- PHP7.0不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php callStatic
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__callStatic_no_magic_php.log 10000
// 結(jié)果
avg: 14μm
max: 130μm
min: 9μm
- PHP7.0使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php callStatic
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__callStatic_magic_php.log 10000
// 結(jié)果
avg: 14μm
max: 159μm
min: 10μm
通過上面的數(shù)據(jù)我們可以看出:
在php5.6中使用__callStatic的腳本執(zhí)行的平均時(shí)間是要慢于不使用,__大概慢3微秒__;在php7.0中使用__callStatic的腳本執(zhí)行的平均時(shí)間是要大致等于不使用__callStatic的;__set
接著,我們來看看__set的實(shí)驗(yàn),php腳本如下:
<?php
/**
* 魔術(shù)方法性能探索
*
* 設(shè)置私有屬性__set
*
* @author TIGERB <https://github.com/TIGERB>
*/
require('./function.php');
if (!isset($argv[1])) {
die('error: variable is_use_magic is empty');
}
$is_use_magic = $argv[1];
/**
* 實(shí)現(xiàn)公共方法設(shè)置私有屬性
*/
class ClassOne
{
/**
* 私有屬性
*
* @var string
*/
private $someVariable = 'private';
public function __construct()
{
# code...
}
public function setSomeVariable($value = '')
{
$this->someVariable = $value;
}
}
/**
* 使用_set設(shè)置私有屬性
*/
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不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php5 set
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__set_no_magic_php5.log 10000
// 結(jié)果
avg: 31μm
max: 110μm
min: 24μm
- PHP5.6使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php5 set
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__set_magic_php5.log 10000
// 結(jié)果
avg: 33μm
max: 138μm
min: 25μm
- PHP7.0不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php set
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__set_no_magic_php.log 10000
// 結(jié)果
avg: 15μm
max: 441μm
min: 11μm
- PHP7.0使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php set
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__set_magic_php.log 10000
// 結(jié)果
avg: 17μm
max: 120μm
min: 11μm
通過上面的數(shù)據(jù)我們可以看出:
使用__set的腳本執(zhí)行的平均時(shí)間是要慢于不使用,__大概慢2微秒__,不論是在php5.6還是php7.0中。__get
接著,我們來看看__get的實(shí)驗(yàn),php腳本如下:
<?php
/**
* 魔術(shù)方法性能探索
*
* 讀取私有屬性__get
*
* @author TIGERB <https://github.com/TIGERB>
*/
require('./function.php');
if (!isset($argv[1])) {
die('error: variable is_use_magic is empty');
}
$is_use_magic = $argv[1];
/**
* 實(shí)現(xiàn)公共方法獲取私有屬性
*/
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不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php5 get
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__get_no_magic_php5.log 10000
// 結(jié)果
avg: 28μm
max: 590μm
min: 20μm
- PHP5.6使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP5.6中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php5 get
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__get_magic_php5.log 10000
// 結(jié)果
avg: 28μm
max: 211μm
min: 22μm
- PHP7.0不使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 no_magic php get
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__get_no_magic_php.log 10000
// 結(jié)果
avg: 16μm
max: 295μm
min: 10μm
- PHP7.0使用魔術(shù)方法數(shù)據(jù)如下,單位微秒μm
// PHP7.0中連續(xù)調(diào)用腳本10000次
sh test 10000 magic php get
// 運(yùn)行數(shù)據(jù)統(tǒng)計(jì)腳本
sh analysis ./logs/__get_magic_php.log 10000
// 結(jié)果
avg: 19μm
max: 525μm
min: 12μm
通過上面的數(shù)據(jù)我們可以看出:
在php5.6中使用__get的腳本執(zhí)行的平均時(shí)間是要大致等于不使用__get的;在php7.0中使用__get的腳本執(zhí)行的平均時(shí)間是要慢于不使用,__大概慢3微秒__。結(jié)語
這里主要測(cè)試了__construct(), __call(), __callStatic(), __get(), __set()這五個(gè)常用的且可有其他實(shí)現(xiàn)方式代替的魔法函數(shù)。通過上面的測(cè)試再回來解答我的疑惑
答:除了使用__construct之外,這里使用其他的魔法方法的時(shí)間大致慢10微妙以內(nèi)。
答:在PHP7中使用與不使用魔術(shù)方法之間的差異和在PHP5.6中近乎一致。
答:通過整個(gè)測(cè)試我們可以看出使不使用魔法方法這之間的執(zhí)行時(shí)間差異大致都是在10微妙以內(nèi)的,所以如果魔法方法可以很好的節(jié)省我們的開發(fā)成本和優(yōu)化我們的代碼結(jié)構(gòu),我們應(yīng)該可以考慮犧牲掉這不到10微妙。而__construct是要快的,所以使用__construct應(yīng)該沒什么異議。
腳本源碼
https://github.com/TIGERB/eas... 來源:https://blog.csdn.net/weixin_34235105/article/details/89088147總結(jié)
以上是生活随笔為你收集整理的PHP魔法函数性能分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蜂蜜水和什么一起减肥?
- 下一篇: 网络中的七层协议与TCP/IP五层模型