パフォーマンスはコードを測定するための重要な基準となることがよくあります。私たちは日々のコーディングでいくつかのマジック メソッドをよく使用します。PHP が提供するこれらのマジック メソッドはプログラムのパフォーマンスに影響しますか?魔法のような方法の使用を減らす必要があるでしょうか?この記事では、テストの比較を使用して、マジック メソッドがパフォーマンスに及ぼす影響を理解します。
疑問
その魔法の方法は本当に性能が悪いのでしょうか?
PHP7 のマジック メソッドのパフォーマンスにまだ問題がありますか?
魔法の方法を合理的に使用するにはどうすればよいですか?
計画
私の計画は次のとおりです:
マジックメソッドを使用した場合と使用しない場合のスクリプト実行時間の差の統計的比較
PHP5.6.26でスクリプトをn回連続実行する- 1
統計的な実行時間の平均/最小/最大値
PHP7.0.12-2でスクリプトをn回連続実行
実行時間の統計的な平均/最小/最大値
テスト
__construct
まず、コンストラクター __construct の実験を見てみましょう。 PHP スクリプトは次のとおりです。
<?php /** * 魔术方法性能探索 * * 构造函数 * * @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]; /** * 构造函数使用类名 */ 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 では、マジック メソッドは使用されません。データは次のとおりです (マイクロ秒単位)。
// 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では以下のようになります。単位はマイクロ秒です。 __construct をコンストラクターとして使用するスクリプトの実行時間は、php5.6 または php7.0 のどちらの場合でも、クラス名をコンストラクターとして使用するよりも速くなり、約 5 ~ 6 マイクロ秒速くなります。
__call
// 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中连续调用脚本10000次 sh test 10000 magic php construct // 运行数据统计脚本 sh analysis ./logs/__construct_magic_php.log 10000 // 结果 avg: 14μs max: 157μs min: 10μs
PHP5.6 マジックメソッドを使用したデータは以下の通り、単位はマイクロ秒 μs<?php
/**
* 魔术方法性能探索
*
* 构造函数
*
* @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];
/**
* 构造函数使用类名
*/
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中连续调用脚本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中连续调用脚本10000次 sh test 10000 magic php5 call // 运行数据统计脚本 sh analysis ./logs/__call_magic_php5.log 10000 // 结果 avg: 29μs max: 392μs min: 22μs
上記のデータから、次のことがわかります:
__call を使用したスクリプトの平均実行時間は、__call を使用しない場合よりも遅くなり、約 2 マイクロ秒遅くなります。 php5.6でもphp7.0でも。
__callStatic
次に、__callStatic の実験を見てみましょう:
// 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
PHP5.6 では、マジック メソッドは使用されません。マイクロ秒 μ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
<?php /** * 魔术方法性能探索 * * 静态重载函数 * * @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静态方法 */ 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中连续调用脚本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中连续调用脚本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中连续调用脚本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中连续调用脚本10000次 sh test 10000 magic php callStatic // 运行数据统计脚本 sh analysis ./logs/__callStatic_magic_php.log 10000 // 结果 avg: 14μs max: 159μs min: 10μs
<?php /** * 魔术方法性能探索 * * 设置私有属性__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]; /** * 实现公共方法设置私有属性 */ 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中连续调用脚本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中连续调用脚本10000次 sh test 10000 magic php5 set // 运行数据统计脚本 sh analysis ./logs/__set_magic_php5.log 10000 // 结果 avg: 33μs max: 138μs min: 25μs
__get
次に、__get の実験を見てみましょう。
// 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
PHP5.6 では、マジック メソッドは使用されません。マイクロ秒 μ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
PHP5.6 マジックメソッドを使用したデータは以下の通り、単位はマイクロ秒 μs
<?php /** * 魔术方法性能探索 * * 读取私有属性__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]; /** * 实现公共方法获取私有属性 */ 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";
PHP7.0 マジックメソッドを使用しないデータは以下の通り、単位はマイクロ秒 μ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
PHP7 0 マジックメソッドを使用したデータは次のとおりです。単位はマイクロ秒 μ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
上記のデータから次のことがわかります。
php5.6 で __get を使用したスクリプトの平均実行時間は、__get を使用しない場合とほぼ同じです。 php7.0 で __get を使用したスクリプトの平均実行時間は、使用しない場合よりも遅くなり、約 3 マイクロ秒遅くなります。
結論
ここでは主に、他の実装メソッド関数で置き換えることができる __construct()、__call()、__callStatic()、__get()、__set() という 5 つの一般的に使用されるマジックをテストしました。上記のテストに合格したら、疑問に答えるために戻ってきます
魔法のメソッドのパフォーマンスは本当に悪いですか? 回答: __construct の使用に加えて、ここで他のマジック メソッドを使用する時間は、およそ 10 マイクロ秒以内です。PHP7 のマジック メソッドのパフォーマンスにまだ問題がありますか?
A: PHP7 でマジック メソッドを使用する場合と使用しない場合の違いは、PHP5.6 の場合とほぼ同じです。
魔法の方法を合理的に使用するにはどうすればよいですか? A: テスト全体を通じて、マジック メソッドを使用しない場合の実行時間の差はおよそ 10 マイクロ秒以内であることがわかります。そのため、マジック メソッドを使用して開発コストを節約し、コードの構造を最適化できるのであれば、できるはずです。 10 マイクロ秒未満を犠牲にすることを検討してください。 __construct は高速であることを目的としているため、__construct を使用することに異論はありません。
以上がPHP で一般的に使用されるマジック メソッドのパフォーマンスの調査の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。