ホームページ  >  記事  >  バックエンド開発  >  PHPマジック関数のパフォーマンスコードの詳細な分析

PHPマジック関数のパフォーマンスコードの詳細な分析

黄舟
黄舟オリジナル
2017-03-09 09:56:371401ブラウズ

バード兄弟のラルエンスが「魔法の方法」を使用することはお勧めできないと言っていたことを思い出しました。それ以来、魔法の方法が関係するたびに、これは写真を撮るのに良い方法ですか?ここ1~2年は仕事と新しい知識の習得に忙しかったため、この道を深く探ることはなく、ぼんやりしていました。今年は私にとって深く勉強する年です。 、それで、今度はこの問題について調査する必要があります。まず、バード兄弟ラルエンスがかつてブログで述べたことを見てみましょう:

PPT を社内の同僚と共有すると、魔法の方法の使用さえも許可されていないことに疑問を抱く人もいます

?最適化の提案は提案です、はい、誰もがそれを悪用したり不謹慎に使用したりするのを防ぎます。コードを書くときに何が遅くて何が速いかを認識でき、マジックメソッドへの不必要な呼び出しを避けることができれば、それがこの最適化の提案が求める効果です。

疑問

  1. 魔法の方法は本当にパフォーマンスが低いのでしょうか?

  2. PHP7 のマジック メソッドのパフォーマンスにまだ問題がありますか?

  3. 魔法の方法を合理的に使用するにはどうすればよいですか?

解決策

疑問に直面した私の解決策は次のとおりです:

  • マジックメソッドを使用した場合と使用しない場合のスクリプト実行の時間差の統計的比較

  • PHP5 でのスクリプトの継続実行.6.26-1 n回

  • 実行時間の平均/最小/最大値の統計

  • PHP7.0.12-2でスクリプトをn回連続実行

  • の統計的な平均/最小/最大値実行時間

現在、私の個人的な能力には限界があるので、より良い計画や提案があれば、教えてください、ありがとう、笑〜

テスト

__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 はマジックメソッドを使用しません。データは次のとおりです。単位はマイクロ秒です

// 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はマジックメソッドを使用しています。データは次のとおりです。単位はマイクロ秒です

// 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を使用したスクリプトの平均実行時間。コンストラクターは、php5.6 または php7.0 のどちらの場合でも、クラス名をコンストラクターとして使用するよりも高速であり、約 5 ~ 6 マイクロ秒高速です

__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 では、マイクロ秒単位で次のようになります。

    // 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 を使用したスクリプトの平均実行時間は、__call を使用しない場合よりも遅くなります。 php5.6でもphp7.0中間でも

約2マイクロ秒

__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 では、マイクロ秒単位で次のようになります。
// 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を使用したスクリプトの平均実行時間は、php5.6よりも遅いです。 __callStatic を使用しない場合、

    約 3 マイクロ秒
  • ; __callStatic を使用したスクリプトの平均実行時間は、__callStatic を使用しない場合とほぼ同じです。次に、__set の実験を見てみましょう。
<?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

    上記データより

  • php5.6 か php7.0 かにかかわらず、__set を使用したスクリプトの平均実行時間は、__set を使用しない場合よりも遅くなり、
約 2 マイクロ秒遅くなります
  • __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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。