[php] PHP로 메모리를 비우는 데 더 좋은 점 : unset () 또는 $ var = null

두 번째는 함수 호출의 오버 헤드를 피한다는 것을 알고 있습니다 ( update , 실제로 언어 구성입니다). 하나가 다른 것보다 낫다면 흥미로울 것입니다. 나는 unset()대부분의 코딩에 사용하고 있지만 최근에는 $var = null대신에 그물에서 발견되는 존경할만한 몇 가지 클래스를 살펴 보았습니다 .

선호하는 것이 있습니까? 추론은 무엇입니까?



답변

2009 년 설정되지 않은 매뉴얼 페이지에서 언급되었습니다 .

unset()변수 이름을 설정합니다. 메모리를 즉시 해제하지 않습니다. PHP의 가비지 콜렉터는 CPU 사이클이 필요하지 않거나 스크립트가 메모리 부족으로 늦어지기 전에 늦게까지 의도적으로 적합 할 때이를 수행합니다.

당신이하고 있다면 $whatever = null;변수의 데이터를 다시 쓰고 있습니다. 메모리를 더 빨리 확보 / 축소 할 수 있지만 실제로 필요한 코드에서 CPU주기를 훔쳐서 전체 실행 시간이 길어질 수 있습니다.

(2013 년 이후로 해당 unset매뉴얼 페이지 에는 해당 섹션이 더 이상 포함되지 않습니다)

php5.3까지 부모-자식 관계와 같이 순환 참조에 두 개의 객체가있는 경우 부모 객체에서 unset ()을 호출하면 자식 객체의 부모 참조에 사용 된 메모리가 해제되지 않습니다. (부모 객체가 가비지 수집 될 때 메모리가 해제되지 않습니다.) ( 버그 33595 )


unset과 = null의 차이점 “이라는 질문에는 몇 가지 차이점이 자세히 설명되어 있습니다.


unset($a)$a기호 테이블에서 제거 합니다. 예를 들면 다음과 같습니다.

$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);

출력 :

Notice: Undefined variable: a in xxx
NULL

그러나 언제 $a = null사용됩니까?

$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);
Outputs:

NULL

그 보인다 $a = null조금 더 빨리 그보다 unset()기호 테이블 항목을 업데이트하면 빨리 제거보다 나타납니다 : 대응.


  • 존재하지 않는 ( unset) 변수 를 사용하려고 하면 오류가 발생하고 변수 표현식의 값이 널이됩니다. (PHP는 다른 무엇을해야합니까? 모든 표현식은 어느 정도 가치가 있어야합니다.)
  • null이 할당 된 변수는 여전히 완벽하게 정상적인 변수입니다.

답변

unset실제로 함수는 아니지만 언어 구문 입니다. 더 이상 a return또는 a보다 함수 호출이 아닙니다 include.

성능 문제 외에도 unset코드를 사용 하면 코드의 의도가 훨씬 명확 해집니다.


답변

변수에 대해 unset ()을 수행하면 본질적으로 변수를 ‘가비지 수집'(PHP에는 실제로는 없지만 예를 들어)으로 표시하므로 메모리를 즉시 사용할 수 없습니다. 변수는 더 이상 데이터를 저장하지 않지만 스택은 더 큰 크기로 유지됩니다. null 메서드를 수행하면 데이터가 삭제되고 스택 메모리가 거의 즉시 축소됩니다.

이것은 개인적인 경험과 다른 사람들로부터 온 것입니다. unset () 함수의 주석은 here을 참조하십시오 .

개인적으로 루프에서 반복 사이에 unset ()을 사용하므로 스택 크기가 지연 될 필요가 없습니다. 데이터는 사라졌지 만 설치 공간은 남아 있습니다. 다음 반복에서 메모리는 이미 PHP에 의해 취해지고 있으므로 다음 변수를 더 빨리 초기화합니다.


답변

<?php
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    $a = NULL;
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds\r\n";



$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    unset($a);
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds\r\n";
?>

“= null”이 더 빠를 것 같습니다.

PHP 5.4 결과 :

  • 0.88389301300049 초 소요
  • 2.1757180690765 초가 걸렸습니다.

PHP 5.3 결과 :

  • 1.7235369682312 초가 걸렸습니다.
  • 2.9490959644318 초 걸렸다

PHP 5.2 결과 :

  • 3.0069220066071 초 걸렸다
  • 4.7002630233765 초가 걸렸습니다.

PHP 5.1 결과 :

  • 2.6272349357605 초 걸렸다
  • 5.0403649806976 초가 걸렸다

PHP 5.0과 4.4에서는 상황이 다르게 보이기 시작합니다.

5.0 :

  • 10.038941144943 초 걸렸다
  • 7.0874409675598 초 소요

4.4 :

  • 소요 7.5352551937103 초
  • 6.6245851516724 초가 걸렸습니다.

microtime (true)은 PHP 4.4에서 작동하지 않으므로 php.net/microtime / Example # 1에 제공된 microtime_float 예제를 사용해야했습니다.


답변

배열 요소와 차이를 만듭니다.

이 예를 고려하십시오

$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

여기에는 키 ‘테스트’가 여전히 존재합니다. 그러나이 예에서는

$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

키가 더 이상 존재하지 않습니다.


답변

참조로 복사 된 변수에 대해 다른 방식으로 작동합니다.

$a = 5;
$b = &$a;
unset($b); // just say $b should not point to any variable
print $a; // 5

$a = 5;
$b = &$a;
$b = null; // rewrites value of $b (and $a)
print $a; // nothing, because $a = null


답변

객체, 특히 지연로드 시나리오에서 가비지 콜렉터가 유휴 CPU 주기로 실행 중임을 고려해야하므로 많은 오브젝트가 작은 시간 페널티를로드 할 때 문제가 발생한다고 가정하면 메모리 확보가 해결됩니다.

GC가 메모리를 수집 할 수있게하려면 time_nanosleep을 사용하십시오. 변수를 null로 설정하는 것이 바람직합니다.

프로덕션 서버에서 테스트 한 결과 원래 작업이 50MB를 소비 한 후 중지되었습니다. nanosleep을 사용한 후 14MB는 일정한 메모리 소비였습니다.

PHP 버전에서 버전으로 변경 될 수있는 GC 동작에 따라 달라집니다. 그러나 그것은 PHP 5.3에서 잘 작동합니다.

예. 이 샘플 (VirtueMart2 Google 피드에서 가져온 코드)

for($n=0; $n<count($ids); $n++)
{
    //unset($product); //usefull for arrays
    $product = null
    if( $n % 50 == 0 )
    {
        // let GC do the memory job
        //echo "<mem>" . memory_get_usage() . "</mem>";//$ids[$n];
        time_nanosleep(0, 10000000);
    }

    $product = $productModel->getProductSingle((int)$ids[$n],true, true, true);
    ...