搜尋
首頁後端開發php教程PHP 魔法函數效能程式碼詳細分析

曾經記得鳥哥Laruence提過不建議使用”魔術方法”,自此之後一旦涉及使用魔術方法的地方,我都會下意識的想一下,這樣寫真的好嗎?由於這一到兩年來一直忙於工作和學習新的知識,所以在這道坎兒上一直沒有做深入的探索一直恍恍惚惚過去了,今年是我進行深入學習的一年,因此現在必須對這個問題做個了結了。我們先來看看鳥哥Laruence博客曾經提到的:

當我把PPT分享給公司的同事的時候, 會有人質疑, 魔術方法都不讓用?

優化的建議, 是建議, 是防止大家濫用, 肆無忌憚的用. 如果你能在寫代碼的時候, 能意識到, 什麼慢, 什麼快, 從而避免一些沒有必要的對魔術方法的調用, 那就是這個優化建議所追求的效果了

疑惑

  1. 魔術方法真的性能比較差嗎?

  2. PHP7裡使用魔術方法的表現還是有問題嗎?

  3. 我們應該如何合理的使用魔術方法?

方案

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

  • 統計比較使用魔術方法和不使用魔術方法腳本執行的時間差異

  • PHP5.6.26-1 下連續執行腳本n次

  • ##統計執行時間的平均值/最小值/最大值

  • PHP7.0.12-2 下連續執行腳本n次

  • 統計執行時間的平均值/最小值/最大值

目前個人能力有限,只能透過這種方式,如果你有更好的方案或建議可以告訴我,謝謝,haha~

測試

__construct

首先我們先來看看建構子__construct的實驗,php腳本如下:

<?php
/**
 * 魔术方法性能探索
 *
 * 构造函数
 *
 * @author TIGERB <http://www.php.cn/;
 */

require(&#39;./function.php&#39;);
if (!isset($argv[1])) {
    die(&#39;error: variable is_use_magic is empty&#39;);
}
$is_use_magic = $argv[1];

/**
 * 构造函数使用类名
 */
class ClassOne
{
    public function classOne()
    {
        # code...
    }
}

/**
 * 构造函数使用魔术函数__construct
 */
class ClassTwo
{
    public function __construct()
    {
        # code...
    }
}

$a = getmicrotime();
if ($is_use_magic === &#39;no_magic&#39;) {
    new ClassOne();
}else {
    new ClassTwo();
}
$b = getmicrotime();

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

  • PHP5.6不使用魔術方法數據如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 no_magic php5 construct
    
    // 运行数据统计脚本
    sh analysis ./logs/__construct_no_magic_php5.log 10000
    
    // 结果
    avg: 34μm
    max: 483μm
    min: 26μm
  • PHP5.6使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 magic php5 construct
    
    // 运行数据统计脚本
    sh analysis ./logs/__construct_magic_php5.log 10000
    
    // 结果
    avg: 28μm
    max: 896μm
    min: 20μm
  • PHP7.0不使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 no_magic php construct
    
    // 运行数据统计脚本
    sh analysis ./logs/__construct_no_magic_php.log 10000
    
    // 结果
    avg: 19μm
    max: 819μm
    min: 13μm
  • PHP7.0使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 magic php construct
    
    // 运行数据统计脚本
    sh analysis ./logs/__construct_magic_php.log 10000
    
    // 结果
    avg: 14μm
    max: 157μm
    min: 10μm
透過上面的資料我們可以看出:

使用__construct作為建構子的腳本執行的平均時間是要快於使用類別名作為建構子的,

大概快5到6微秒 ,不論是在php5.6還是php7.0。

__call

接著,我們來看看__call的實驗,php腳本如下:

<?php
/**
 * 魔术方法性能探索
 *
 * 构造函数
 *
 * @author TIGERB <http://www.php.cn/;
 */

require(&#39;./function.php&#39;);
if (!isset($argv[1])) {
    die(&#39;error: variable is_use_magic is empty&#39;);
}
$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 === &#39;no_magic&#39;) {
    $instance = new ClassOne();
    $instance->test();
}else {
    $instance = new ClassTwo();
    $instance->test();
}
$b = getmicrotime();

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

  • PHP5.6不使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 no_magic php5 call
    
    // 运行数据统计脚本
    sh analysis ./logs/__call_no_magic_php5.log 10000
    
    // 结果
    avg: 27μm
    max: 206μm
    min: 20μm
  • PHP5.6使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 magic php5 call
    
    // 运行数据统计脚本
    sh analysis ./logs/__call_magic_php5.log 10000
    
    // 结果
    avg: 29μm
    max: 392μm
    min: 22μm
  • PHP7.0不使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 no_magic php call
    
    // 运行数据统计脚本
    sh analysis ./logs/__call_no_magic_php.log 10000
    
    // 结果
    avg: 16μm
    max: 256μm
    min: 10μm
  • PHP7.0使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 magic php call
    
    // 运行数据统计脚本
    sh analysis ./logs/__call_magic_php.log 10000
    
    // 结果
    avg: 18μm
    max: 2459μm
    min: 11μm
透過上面的資料我們可以看出:

#使用__call的腳本執行的平均時間是要慢於不使用,

大概慢2微秒 ,不論是在php5.6還是php7.0。

__callStatic

接著,我們來看看__callStatic的實驗,php腳本如下:

<?php
/**
 * 魔术方法性能探索
 *
 * 静态重载函数
 *
 * @author TIGERB <http://www.php.cn/;
 */

require(&#39;./function.php&#39;);
if (!isset($argv[1])) {
    die(&#39;error: variable is_use_magic is empty&#39;);
}
$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 === &#39;no_magic&#39;) {
    ClassOne::test();
}else {
    ClassTwo::test();
}
$b = getmicrotime();

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

  • PHP5.6不使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 no_magic php5 callStatic
    
    // 运行数据统计脚本
    sh analysis ./logs/__callStatic_no_magic_php5.log 10000
    
    // 结果
    avg: 25μm
    max: 129μm
    min: 19μm
  • PHP5.6使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 magic php5 callStatic
    
    // 运行数据统计脚本
    sh analysis ./logs/__callStatic_magic_php5.log 10000
    
    // 结果
    avg: 28μm
    max: 580μm
    min: 20μm
  • PHP7.0不使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 no_magic php callStatic
    
    // 运行数据统计脚本
    sh analysis ./logs/__callStatic_no_magic_php.log 10000
    
    // 结果
    avg: 14μm
    max: 130μm
    min: 9μm
  • PHP7.0使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 magic php callStatic
    
    // 运行数据统计脚本
    sh analysis ./logs/__callStatic_magic_php.log 10000
    
    // 结果
    avg: 14μm
    max: 159μm
    min: 10μm
透過上面的資料我們可以看出:

#在php5.6中使用__callStatic的腳本執行的平均時間是要慢於不使用,

大概慢3微秒 ;在php7.0中使用__callStatic的腳本執行的平均時間是要大致等於不使用__callStatic的;

__set

#接著,我們來看看__set的實驗,php腳本如下:

<?php
/**
 * 魔术方法性能探索
 *
 * 设置私有属性__set
 *
 * @author TIGERB <http://www.php.cn/;
 */

require(&#39;./function.php&#39;);
if (!isset($argv[1])) {
    die(&#39;error: variable is_use_magic is empty&#39;);
}
$is_use_magic = $argv[1];

/**
 * 实现公共方法设置私有属性
 */
class ClassOne
{
    /**
     * 私有属性
     *
     * @var string
     */
    private $someVariable = &#39;private&#39;;

    public function __construct()
    {
        # code...
    }

    public function setSomeVariable($value = &#39;&#39;)
    {
        $this->someVariable = $value;
    }
}

/**
 * 使用_set设置私有属性
 */
class ClassTwo
{
    /**
     * 私有属性
     *
     * @var string
     */
    private $someVariable = &#39;private&#39;;

    public function __construct()
    {
        # code...
    }

    public function __set($name = &#39;&#39;, $value = &#39;&#39;)
    {
        $this->$name = $value;
    }
}

$a = getmicrotime();
if ($is_use_magic === &#39;no_magic&#39;) {
    $instance = new ClassOne();
    $instance->setSomeVariable(&#39;public&#39;);
}else {
    $instance = new ClassTwo();
    $instance->someVariable = &#39;public&#39;;
}
$b = getmicrotime();

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

  • PHP5.6不使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 no_magic php5 set
    // 运行数据统计脚本
    sh analysis ./logs/__set_no_magic_php5.log 10000
    
    // 结果
    avg: 31μm
    max: 110μm
    min: 24μm
  • PHP5.6使用魔術方法資料如下,單位微秒μm

  • // PHP5.6中连续调用脚本10000次
    sh test 10000 magic php5 set
    // 运行数据统计脚本
    sh analysis ./logs/__set_magic_php5.log 10000
    
    // 结果
    avg: 33μm
    max: 138μm
    min: 25μm
  • PHP7.0不使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 no_magic php set
    // 运行数据统计脚本
    sh analysis ./logs/__set_no_magic_php.log 10000
    
    // 结果
    avg: 15μm
    max: 441μm
    min: 11μm
  • PHP7.0使用魔術方法資料如下,單位微秒μm

  • // PHP7.0中连续调用脚本10000次
    sh test 10000 magic php set
    // 运行数据统计脚本
    sh analysis ./logs/__set_magic_php.log 10000
    
    // 结果
    avg: 17μm
    max: 120μm
    min: 11μm
透過上面的資料我們可以看出:

使用__set的腳本執行的平均時間是要慢於不使用,

大概慢2微秒 ,不論是在php5. 6還是php7.0中。

__get

接著,我們來看看__get的實驗,php腳本如下:

<?php
/**
 * 魔术方法性能探索
 *
 * 读取私有属性__get
 *
 * @author TIGERB <http://www.php.cn/;
 */

require(&#39;./function.php&#39;);
if (!isset($argv[1])) {
    die(&#39;error: variable is_use_magic is empty&#39;);
}
$is_use_magic = $argv[1];

/**
 * 实现公共方法获取私有属性
 */
class ClassOne
{
    /**
     * 私有属性
     *
     * @var string
     */
    private $someVariable = &#39;private&#39;;

    public function __construct()
    {
        # code...
    }

    public function getSomeVariable()
    {
        return $this->someVariable;
    }
}

/**
 * 使用_get获取私有属性
 */
class ClassTwo
{
    /**
     * 私有属性
     *
     * @var string
     */
    private $someVariable = &#39;private&#39;;

    public function __construct()
    {
        # code...
    }

    public function __get($name = &#39;&#39;)
    {
        return $this->$name;
    }
}

$a = getmicrotime();
if ($is_use_magic === &#39;no_magic&#39;) {
    $instance = new ClassOne();
    $instance->getSomeVariable();
}else {
    $instance = new ClassTwo();
    $instance->someVariable;
}
$b = getmicrotime();

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

  • PHP5.6不使用魔术方法数据如下,单位微秒μm

// PHP5.6中连续调用脚本10000次
sh test 10000 no_magic php5 get
// 运行数据统计脚本
sh analysis ./logs/__get_no_magic_php5.log 10000

// 结果
avg: 28μm
max: 590μm
min: 20μm
  • PHP5.6使用魔术方法数据如下,单位微秒μm

// PHP5.6中连续调用脚本10000次
sh test 10000 magic php5 get
// 运行数据统计脚本
sh analysis ./logs/__get_magic_php5.log 10000

// 结果
avg: 28μm
max: 211μm
min: 22μm
  • PHP7.0不使用魔术方法数据如下,单位微秒μm

// PHP7.0中连续调用脚本10000次
sh test 10000 no_magic php get
// 运行数据统计脚本
sh analysis ./logs/__get_no_magic_php.log 10000

// 结果
avg: 16μm
max: 295μm
min: 10μm
  • PHP7.0使用魔术方法数据如下,单位微秒μm

// PHP7.0中连续调用脚本10000次
sh test 10000 magic php get
// 运行数据统计脚本
sh analysis ./logs/__get_magic_php.log 10000

// 结果
avg: 19μm
max: 525μm
min: 12μm

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

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

结语

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

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

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

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

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

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

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

  

以上是PHP 魔法函數效能程式碼詳細分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何防止會話固定攻擊?如何防止會話固定攻擊?Apr 28, 2025 am 12:25 AM

防止會話固定攻擊的有效方法包括:1.在用戶登錄後重新生成會話ID;2.使用安全的會話ID生成算法;3.實施會話超時機制;4.使用HTTPS加密會話數據,這些措施能確保應用在面對會話固定攻擊時堅不可摧。

您如何實施無會話身份驗證?您如何實施無會話身份驗證?Apr 28, 2025 am 12:24 AM

實現無會話身份驗證可以通過使用JSONWebTokens(JWT)來實現,這是一種基於令牌的認證系統,所有的必要信息都存儲在令牌中,無需服務器端會話存儲。 1)使用JWT生成和驗證令牌,2)確保使用HTTPS防止令牌被截獲,3)在客戶端安全存儲令牌,4)在服務器端驗證令牌以防篡改,5)實現令牌撤銷機制,如使用短期訪問令牌和長期刷新令牌。

PHP會議有哪些常見的安全風險?PHP會議有哪些常見的安全風險?Apr 28, 2025 am 12:24 AM

PHP會話的安全風險主要包括會話劫持、會話固定、會話預測和會話中毒。 1.會話劫持可以通過使用HTTPS和保護cookie來防範。 2.會話固定可以通過在用戶登錄前重新生成會話ID來避免。 3.會話預測需要確保會話ID的隨機性和不可預測性。 4.會話中毒可以通過對會話數據進行驗證和過濾來預防。

您如何銷毀PHP會議?您如何銷毀PHP會議?Apr 28, 2025 am 12:16 AM

銷毀PHP會話需要先啟動會話,然後清除數據並銷毀會話文件。 1.使用session_start()啟動會話。 2.用session_unset()清除會話數據。 3.最後用session_destroy()銷毀會話文件,確保數據安全和資源釋放。

如何更改PHP中的默認會話保存路徑?如何更改PHP中的默認會話保存路徑?Apr 28, 2025 am 12:12 AM

如何改變PHP的默認會話保存路徑?可以通過以下步驟實現:在PHP腳本中使用session_save_path('/var/www/sessions');session_start();設置會話保存路徑。在php.ini文件中設置session.save_path="/var/www/sessions"來全局改變會話保存路徑。使用Memcached或Redis存儲會話數據,如ini_set('session.save_handler','memcached');ini_set(

您如何修改PHP會話中存儲的數據?您如何修改PHP會話中存儲的數據?Apr 27, 2025 am 12:23 AM

tomodifyDataNaphPsession,startTheSessionWithSession_start(),然後使用$ _sessionToset,修改,orremovevariables.1)startThesession.2)setthesession.2)使用$ _session.3)setormodifysessessvariables.3)emovervariableswithunset()

舉一個在PHP會話中存儲數組的示例。舉一個在PHP會話中存儲數組的示例。Apr 27, 2025 am 12:20 AM

在PHP會話中可以存儲數組。 1.啟動會話,使用session_start()。 2.創建數組並存儲在$_SESSION中。 3.通過$_SESSION檢索數組。 4.優化會話數據以提升性能。

垃圾收集如何用於PHP會議?垃圾收集如何用於PHP會議?Apr 27, 2025 am 12:19 AM

PHP會話垃圾回收通過概率機制觸發,清理過期會話數據。 1)配置文件中設置觸發概率和會話生命週期;2)可使用cron任務優化高負載應用;3)需平衡垃圾回收頻率與性能,避免數據丟失。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)