성능은 코드를 측정하는 중요한 기준인 경우가 많습니다. 우리는 일상적인 코딩에서 몇 가지 매직 메소드를 자주 사용합니다. PHP가 제공하는 이러한 매직 메소드가 프로그램 성능에 영향을 미칠까요? 매직 메소드의 사용을 줄여야 합니까? 이 기사에서는 테스트 비교를 사용하여 매직 메소드가 성능에 미치는 영향을 이해합니다.
의심
매직메소드는 정말 성능이 떨어지는 걸까요?
PHP7의 매직 메소드 성능에 여전히 문제가 있나요?
마법을 어떻게 합리적으로 사용해야 할까요?
Plan
의심에 직면한 내 계획은 다음과 같습니다.
매직 메소드를 사용하는 경우와 사용하지 않는 경우의 스크립트 실행 시간 차이를 통계적으로 비교합니다.
PHP5.6.26-1에서 스크립트를 n번 연속 실행합니다.
통계적 실행 시간의 평균/최소/최대값
PHP7.0.12-2에서 스크립트를 n번 연속 실행합니다.
실행 시간의 통계적 평균/최소/최대값
Test
__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
다음으로 __call 실험을 살펴보겠습니다. php 스크립트는 다음과 같습니다.
// 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
<?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
__callStatic
다음으로 __callStatic 실험을 살펴보겠습니다. php 스크립트는 다음과 같습니다.
// 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
// 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
__set
다음으로 __set 실험을 살펴보겠습니다. 스크립트는 다음과 같습니다.
// 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 실험을 살펴보겠습니다. php 스크립트는 다음과 같습니다.
// 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
// 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
<?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";
// 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
// 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
결론
여기서 우리는 주로 일반적으로 사용되는 다섯 가지 매직인 __construct(), __call(), __callStatic(), __get(), __set()을 테스트했습니다. 이는 다른 구현 방법 함수로 대체될 수 있습니다. 위 테스트를 통과한 후, 다시 돌아와서 제 의심에 대한 답을 드리겠습니다
매직 메소드의 성능이 정말 형편없나요? 답변: __construct를 사용하는 것 외에도 여기서 다른 마법 메서드를 사용하는 시간은 대략 10마이크로초 이내입니다.
PHP7의 매직 메소드 성능에 여전히 문제가 있나요?
A: PHP7에서 매직 메소드를 사용하는 것과 사용하지 않는 것의 차이는 PHP5.6과 거의 같습니다.
마술방법을 어떻게 합리적으로 사용해야 할까요?
A: 전체 테스트를 통해 매직 메서드를 사용하지 않은 경우의 실행 시간 차이가 대략 10마이크로초 이내라는 것을 알 수 있습니다. 따라서 매직 메서드를 사용하면 개발 비용을 절약하고 코드 구조를 최적화할 수 있다면 다음과 같은 작업을 수행할 수 있을 것입니다. 10마이크로초 미만의 희생을 고려하는 것입니다. __construct는 속도가 빠르도록 설계되었으므로 __construct 사용에 반대할 필요가 없습니다.
위 내용은 PHP의 일반적인 매직 메소드 성능 탐색의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!