Laruence 형제가 "마술 방법"을 사용하는 것은 권장하지 않는다고 언급한 것을 기억합니다. 그 이후로 마법 방법이 포함될 때마다 무의식적으로 생각하게 됩니다. 이것이 사진을 찍는 좋은 방법일까요? 지난 1~2년 동안 일하느라 바빠서 새로운 지식을 배우느라 이 길에 대한 깊이 있는 탐구를 하지 못하고 올해는 깊이 공부해야 할 한 해였습니다. , 이제 이 문제에 대해 조사를 좀 해야 합니다. 먼저 Bird Brother Laruence가 자신의 블로그에서 언급한 내용을 살펴보겠습니다.
회사 동료들과 PPT를 공유할 때 마법의 방법도 허용되지 않는다는 의문을 제기하는 사람들이 있습니다.
최적화 제안은 사람들이 이를 남용하거나 부주의하게 사용하는 것을 방지하기 위한 제안입니다. 코드를 작성할 때 무엇이 느리고 무엇이 빠른지 알 수 있다면 불필요한 매직 메소드 호출을 피할 수 있습니다. 과연 이 최적화 제안이 추구하는 효과는 과연
매직메소드는 정말 성능이 떨어지는 걸까요?
PHP7의 매직 메소드 성능에 여전히 문제가 있나요?
매직 메소드를 어떻게 합리적으로 사용해야 할까요?
의심에 직면한 내 계획은 다음과 같습니다.
마술 방법을 사용하는 것과 사용하지 않는 것의 통계적 비교 매직 메소드 스크립트의 실행 시간 차이
PHP5.6.26-1에서 스크립트가 n번 연속 실행
평균 /최소 통계 실행 시간 값/최대 값
PHP7.0.12-2에서 스크립트 n번 연속 실행
평균 통계/ 최소/최대 실행 시간 값
현재 제 개인 능력이 한계가 있어서 이 방법밖에 못 쓰겠습니다. 더 좋은 계획이나 제안이 있으면 알려주시면 감사하겠습니다. 하하. ~
우선 생성자 __construct의 실험을 살펴보겠습니다. PHP 스크립트는 다음과 같습니다.
<?php /** * 魔术方法性能探索 * * 构造函数 * * @author TIGERB <http://www.php.cn/; */ 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은 매직 메소드 데이터를 사용하지 않습니다. 단위는 마이크로초 μ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를 사용하는 스크립트의 평균 실행 시간은 클래스 이름을 생성자로 사용하는 것보다 빠릅니다. 는 php5에서 모두 약 5~6 마이크로초 더 빠릅니다. 6 및 php7.0.
다음으로 __call 실험을 살펴보겠습니다. php 스크립트는 다음과 같습니다.
<?php /** * 魔术方法性能探索 * * 构造函数 * * @author TIGERB <http://www.php.cn/; */ 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은 사용하지 않습니다. 매직 메소드 데이터는 다음과 같습니다. 단위 마이크로초 μ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은 매직 방법을 사용합니다. 마이크로초 단위는 다음과 같습니다.
// 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 실험을 살펴보겠습니다. php 스크립트는 다음과 같습니다.
<?php /** * 魔术方法性能探索 * * 静态重载函数 * * @author TIGERB <http://www.php.cn/; */ 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은 사용하지 않습니다. 매직 메소드 데이터는 다음과 같습니다. 단위 마이크로초 μ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은 매직 방법을 사용합니다. 마이크로초 단위는 다음과 같습니다.
// 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('./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μm max: 110μm min: 24μ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中连续调用脚本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中连续调用脚本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.0이든 php7.0이든 상관없습니다. __get
<?php /** * 魔术方法性能探索 * * 读取私有属性__get * * @author TIGERB <http://www.php.cn/; */ 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不使用魔术方法数据如下,单位微秒μ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()这五个常用的且可有其他实现方式代替的魔法函数。通过上面的测试再回来解答我的疑惑
魔术方法真的性能比较差吗?
答:除了使用__construct之外,这里使用其他的魔法方法的时间大致慢10微妙以内。
PHP7里使用魔术方法的性能还是存在问题吗?
答:在PHP7中使用与不使用魔术方法之间的差异和在PHP5.6中近乎一致。
我们应该如何合理的使用魔术方法?
答:通过整个测试我们可以看出使不使用魔法方法这之间的执行时间差异大致都是在10微妙以内的,所以如果魔法方法可以很好的节省我们的开发成本和优化我们的代码结构,我们应该可以考虑牺牲掉这不到10微妙。而__construct是要快的,所以使用__construct应该没什么异议。
위 내용은 PHP 매직함수 성능 코드 상세 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!