PHP (> = 5.0)에서 참조로 전달하는 것이 더 빠릅니까?
PHP에서는 다음과 같이 함수 선언의 매개 변수 앞에 앰퍼샌드를 추가하여 함수 매개 변수를 참조로 전달할 수 있습니다.
function foo(&$bar)
{
// ...
}
지금, 나는이이 것을 알고 하지 성능을 향상시킬 수 있지만, 기능이 정상적으로 자신의 범위이다 변수를 변경할 수 있도록 설계되었습니다.
대신 PHP는 변경 될 때까지 객체 (및 배열)를 복사하는 것을 피하기 위해 Copy On Write를 사용하는 것 같습니다. 따라서 매개 변수를 변경하지 않는 함수의 경우 효과는 참조로 전달한 것과 동일해야합니다.
그러나 Copy On Write 논리가 참조에 의한 전달에서 단락되어 성능에 영향을 미치는지 궁금합니다.
ETA : 확실히, 나는 그것이 더 빠르지 않다고 가정하고 이것이 레퍼런스가 아닌 것을 잘 알고 있습니다. 그래서 저는 제 추측이 꽤 좋다고 생각합니다. 저는 그저 내부에서 확실히 무슨 일이 일어나고 있는지 정말로 아는 사람으로부터 답을 찾고 있습니다. PHP 개발 5 년 동안 저는 소스를 읽는 것보다 PHP 내부에 대한 양질의 정보를 얻는 것이 항상 어려웠습니다.
Zend Engine은 copy-on-write를 사용하며 참조를 직접 사용하면 약간의 추가 오버 헤드가 발생합니다. 이 언급 은 글을 쓰는 시점 에서만 찾을 수 있으며 매뉴얼의 주석 에는 다른 링크가 포함되어 있습니다.
(편집) 객체 및 참조 에 대한 매뉴얼 페이지 에는 객체 변수가 참조와 어떻게 다른지에 대한 정보가 조금 더 있습니다.
문자열이 20kB 인 함수를 호출하는 100,000 회 반복 테스트에서 결과는 다음과 같습니다.
매개 변수를 읽고 사용하는 기능
pass by value: 0.12065005 seconds
pass by reference: 1.52171397 seconds
파라미터 쓰기 / 변경 기능
pass by value: 1.52223396 seconds
pass by reference: 1.52388787 seconds
결론
매개 변수를 값으로 전달하는 것이 항상 더 빠릅니다.
함수가 전달 된 변수의 값을 변경하는 경우 실제 목적 상 값으로 전달하는 것보다 참조로 전달하는 것과 동일합니다.
주어진 답이 확실하지 않아서 이것에 대해 몇 가지 테스트를 실행했습니다.
내 결과는 참조로 큰 배열이나 문자열을 전달하는 것이 훨씬 더 빠르다는 것을 보여줍니다.
내 결과는 다음과 같습니다.
Y 축 (실행)은 1 초 * 10에서 함수를 호출 할 수있는 횟수입니다.
테스트는 각 기능 / 변수에 대해 8 회 반복되었습니다.
그리고 내가 사용한 변수는 다음과 같습니다.
$large_array = array_fill(PHP_INT_MAX / 2, 1000, 'a');
$small_array = array('this', 'is', 'a', 'small', 'array');
$large_object = (object)$large_array;
$large_string = str_repeat('a', 100000);
$small_string = 'this is a small string';
$value = PHP_INT_MAX / 2;
다음은 기능입니다.
function pass_by_ref(&$var) {
}
function pass_by_val($var) {
}
두 개의 동일한 함수에 전달하는 10k 바이트 문자열의 값과 참조를 실험했습니다. 하나는 값으로 인수를 가져오고 두 번째는 참조로 인수를받습니다. 인수를 취하고 간단한 처리를하고 값을 반환하는 일반적인 함수였습니다. 나는 둘 다 100,000 번의 호출을했고 레퍼런스가 성능을 높이기 위해 설계되지 않았다는 것을 알아 냈습니다. 레퍼런스의 이익은 4-5 %에 가깝고 문자열이 충분히 커질 때만 증가합니다 (10 만 이상, 6-7 % 향상) . 그래서 내 결론은 성능을 높이기 위해 참조를 사용하지 않는다는 것입니다.
PHP 버전 5.3.1을 사용했습니다.
나는 그것이 더 빠르지 않다고 확신합니다. 또한 성능 향상을 위해 참조를 사용하지 않도록 설명서에 구체적으로 나와 있습니다.
편집 : 그것이 말하는 곳을 찾을 수 없지만 거기에 있습니다!
코드를 테스트하는 것보다 더 좋은 것은 없습니다
<?PHP
$r = array();
for($i=0; $i<500;$i++){
$r[]=5;
}
function a($r){
$r[0]=1;
}
function b(&$r){
$r[0]=1;
}
$start = microtime(true);
for($i=0;$i<9999;$i++){
//a($r);
b($r);
}
$end = microtime(true);
echo $end-$start;
?>
최종 결과! 배열이 클수록 (또는 호출 수가 많을수록) 차이가 커집니다. 따라서이 경우 함수 내에서 값이 변경되기 때문에 참조로 호출하는 것이 더 빠릅니다.
그렇지 않으면 "참조 별"과 "값별"사이에 실제적인 차이가 없습니다. 컴파일러는 필요가 없을 때마다 새 복사본을 만들지 않을만큼 똑똑합니다.
저는 제가 작업하고있는 프로젝트를 기반으로 한 실제 사례로 이것을 벤치마킹하려고했습니다. 늘 그렇듯이 차이는 사소하지만 결과는 다소 예상치 못한 것이었다. 내가 본 대부분의 벤치 마크에서 호출 된 함수는 실제로 전달 된 값을 변경하지 않습니다. 간단한 str_replace ()를 수행했습니다.
**Pass by Value Test Code:**
$originalString=''; // 1000 pseudo-random digits
function replace($string) {
return str_replace('1', 'x',$string);
}
$output = '';
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);
for ($i = 0; $i < 10; $i++ ) {
for ($j = 0; $j < 1000000; $j++) {
$string = $originalString;
$string = replace($string);
}
}
/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "\n" . 'Total Time' .
': ' . $totalTime;
$output .= "\n" . $string;
echo $output;
참조 테스트 코드 통과
제외하고 동일
function replace(&$string) {
$string = str_replace('1', 'x',$string);
}
/* ... */
replace($string);
몇 초 안에 결과 (1,000 만 회 반복) :
PHP 5
Value: 14.1007
Reference: 11.5564
PHP 7
Value: 3.0799
Reference: 2.9489
The difference is a fraction of a millisecond per function call, but for this use case, passing by reference is faster in both PHP 5 and PHP 7.
(Note: the PHP 7 tests were performed on a faster machine -- PHP 7 is faster, but probably not that much faster.)
Is simple, there is no need to test anything. Depends on use-case.
Pass by value will ALWAYS BE FASTER BY VALUE than reference for small amount of arguments. This depends by how many variables that architecture allows to be passed through registers (ABI).
For example x64 will allow you 4 values 64 bit each to be passed through registers. https://en.wikipedia.org/wiki/X86_calling_conventions
This is because you don't have to de-referentiate the pointers, just use value directly.
전달해야하는 데이터가 ABI보다 크면 나머지 값이 누적됩니다. 이 경우 배열 또는 객체 (예 : 클래스 또는 구조 + 헤더)는 항상 참조에 의해 더 빠릅니다.
이는 참조가 데이터에 대한 포인터 일 뿐이며 (데이터 자체가 아님) 고정 된 크기 (예 : 머신에 따라 32 비트 또는 64 비트)이기 때문입니다. 그 포인터는 하나의 CPU 레지스터에 맞을 것입니다.
PHP는 C / C ++로 작성되었으므로 동일한 동작을 기대합니다.
객체를 전달할 때 & 연산자를 추가 할 필요가 없습니다. PHP에서 5+ 객체는 어쨌든 참조로 전달됩니다.
참고 URL : https://stackoverflow.com/questions/178328/in-php-5-0-is-passing-by-reference-faster
'program story' 카테고리의 다른 글
SDK 플랫폼 도구 버전 ((23))이 너무 오래되어 API 23으로 컴파일 된 API를 확인할 수 없습니다. (0) | 2020.11.20 |
---|---|
다른 파일에서 클래스 가져 오기 (0) | 2020.11.20 |
Rails에서 require, require_dependency 및 상수를 다시로드하는 방법은 무엇입니까? (0) | 2020.11.20 |
PHP에서 간단한 크롤러를 어떻게 만듭니 까? (0) | 2020.11.20 |
Java 클래스를 프로그래밍 방식으로 컴파일하고 인스턴스화하는 방법은 무엇입니까? (0) | 2020.11.20 |