2

두 변수가 있고 모두 null과 같아야한다고 가정합니다. (더 현실적으로 나는 많은 양의 null을 포함하는 배열에 대해 생각하고 있지만 "두 변수"시나리오로 충분합니다.) 분명히 여러 가지 방법으로이 작업을 수행 할 수 있습니다. 나는이 (방법 1) 수행 할 수 있습니다 'a''b' : 나의 이해함으로써PHP null 및 copy-on-write

$a = null; 
$b = $a; 

을,이 결과는 심볼 테이블에 두 개의 항목이 가리키는 하나 zval 있다는 것입니다. 그러나 양자 택일 일이 (방법 2) 할 수 있습니다

$a = null; 
$b = null; 

은 순진하게도 일이 두 가지 zvals 될 것을 기대를, 각각의 심볼 테이블에서 하나 개의 항목으로 지적했다.

는 값 null$master_null 변수를 만들 수 (zval/메모리 사용의 관점에서)보다 효율적으로, 당신이 큰 배열을 갖고 싶어하고, 경우에 배열의 많은 요소가 null 될 것이라고이에서 따르는가 $master_null을 사용하여 할당하여 배열의 null 요소를 씁니다.

+0

왜 시험해 보지 않으시겠습니까? 충분히 단순 해 보입니다. – Halcyon

+0

@Frits : 어떤 zvals가 스크립트에서 존재하는지 확인하는 방법을 모르겠습니다. 각 경우의 PHP 동작은 동일합니다. 은닉 된 내부 차액은 사용자가 부담합니다. – Hammerite

+0

하지만 효과적인 메모리 속성은 숨겨져 있지 않습니다. 이것은 당신이 옳게 알고 싶은 것입니까? – Halcyon

답변

2

이 스크립트를 고려 : 여기에 위의 코멘트 예에서


은 메모리 사용량입니다

내 컴퓨터 출력에
$arr = array(); 
for ($i = 0; $i < 100000; $i++) $arr[] = null; 
echo memory_get_usage() . "\n"; 

: 21687696, 즉 사용되는 메모리 21 MB입니다 . 반면에 이것을 사용하면 :

$master_null = null; 
$arr = array(); 
for ($i = 0; $i < 100000; $i++) $arr[] = $master_null; 
echo memory_get_usage() . "\n"; 

출력 : 13686832, 13MB입니다. 이 정보를 바탕으로, 당신은 메모리 사용량이 당신의 걱정거리라고 생각할 수 있습니다. 사실 "master null"변수를 실제로 사용하는 것이 더 낫습니다. 그러나 여전히 배열의 모든 항목을 가져야하며 HashTable (배열의 내부 표현)에있는 모든 항목은 일부 메모리를 사용합니다.

zvals 및 참조에서 더 깊이 파고 싶으면 debug_zval_dump 함수를 사용하는 것이 좋습니다. 변수 $ x와 $ q를 모두 NULL 있지만, 그들이하지 않는 것을

string(3) "abc" refcount(5) 
NULL refcount(5) 
NULL refcount(2) 

을 그리고 이것은 의미 :

$a = $b = $c = $d = "abc"; 
debug_zval_dump($a); 
$x = $y = $z = $w = null; 
debug_zval_dump($x); 
$q = null; 
debug_zval_dump($q); 

출력 : 그것을 사용하면 변수가 같은 zval을 공유하는, 볼 수 있습니다 같은 zval. 그러나 $ x와 $ y는 같은 zval을 공유합니다. 왜냐하면 그것들은 서로 할당되기 때문입니다. 나는 당신이 함수 debug_zval_dump을 알고 있다고 생각하지만 그렇지 않다면, refcount 설명을주의 깊게 읽으십시오. http://php.net/manual/en/function.debug-zval-dump.php.

또한 내 게시물의 마지막 부분에서이 정보가 PHP 내부에 대한 더 나은 지식을 얻는 데 유용 할 수 있다고 말하고 싶습니다. 최적화를 수행하는 것은 매우 소용이 없습니다. 주로 스크립트 최적화를 시작하기에 훨씬 좋은 곳이 그러한 마이크로 최적화보다 많기 때문입니다. 또한 이것은 사양의 일부는 아니지만 PHP 작성자는 앞으로이 동작을 변경할 수 있습니다 (예 : 모든 NULL 변수가 향후 버전에서 동일한 zval을 공유 할 수 있음).

0

모두 달성 할 수있는 것은 $master_null이라는 추가 변수가 있다는 것입니다. 그들은 모두 null을 가리 킵니다. 그들 각각이 $master_null을 가리키는 것은 같은 것입니다.

+0

나는 내 질문의 본질을 이해하고 있는지 확신하지 못합니다. – Hammerite

1

내가 아는 바로는 PHP zval 컨테이너에는 참조 계산 논리가 있습니다. 따라서 내 느낌은 참조를 사용하여 모든 NULL 값을 초기화하는 & $ master_null을 사용하면 zval 컨테이너에 대해 동일한 참조로 배열의 모든 NULL 항목을 저장할 수 있다고 생각합니다.

# php -r '$var1 = NULL; $var2 = $var1; $var3 = $var1; debug_zval_dump(&$var1); debug_zval_dump(&$var2); debug_zval_dump(&$var3);' 
&NULL refcount(2) 
&NULL refcount(2) 
&NULL refcount(2) 

현재 PHP의 reference counting basis에 대한 자세한 읽을 수 있습니다 :이 링크에서 읽을 가치가

무언가가있다 : 따라서

PHP is smart enough not to copy the actual variable container 
when it is not necessary. Variable containers get destroyed 
when the "refcount" reaches zero. The "refcount" gets decreased by 
one when any symbol linked to the variable container leaves the 
scope (e.g. when the function ends) or when unset() is called on a symbol. 

당신이 사용할 때마다 여기에

은 예입니다 & $ master_null이면 "refcount"가 증가하고 "refcount"가 0이되면 변수 컨테이너가 메모리에서 제거됩니다.

# php -r '$arr = array(); for ($i = 0; $i < 100000; $i++) $arr[] = null; echo memory_get_usage() . "\n";' 
11248372 
# php -r '$master_null = null; $arr = array(); for ($i = 0; $i < 100000; $i++) $arr[] = &$master_null; echo memory_get_usage() . "\n";' 
6848488 
# php -r '$master_null = null; $arr = array(); for ($i = 0; $i < 100000; $i++) $arr[] = $master_null; echo memory_get_usage() . "\n";' 
6848468