복붙노트

PHP로 메모리를 비우는 것이 더 낫다 : unset () 또는 $ var = null

PHP

PHP로 메모리를 비우는 것이 더 낫다 : unset () 또는 $ var = null

두 번째 함수 호출은 함수 호출의 오버 헤드를 피할 수 있습니다 (실제로는 언어 구조입니다). 그러나 하나가 다른 것보다 낫다는 것을 아는 것은 흥미로울 것입니다. unset ()을 사용하여 대부분의 코딩 작업을 해왔지만 최근에는 $ var = null을 대신 사용하는 그물망에서 발견 된 존경할만한 클래스를 살펴 보았습니다.

선호하는 것이 있습니까? 그 이유는 무엇입니까?

해결법

  1. ==============================

    1.그것은 2009 년 unset 매뉴얼의 페이지에서 언급되었습니다 :

    그것은 2009 년 unset 매뉴얼의 페이지에서 언급되었습니다 :

    (2013 년 이래로, 설정되지 않은 맨 페이지에는 더 이상 해당 섹션이 포함되지 않습니다)

    php5.3이 될 때까지 부모 참조에서와 같이 순환 참조에 두 개의 객체가있는 경우 부모 객체에서 unset ()을 호출해도 자식 객체의 부모 참조에 사용 된 메모리가 해제되지 않습니다. (부모 객체가 가비지 수집 될 때 메모리가 해제되지 않습니다.) (bug 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 = str_repeat('hello world ', 100);
    $a = null;
    var_dump($a);
    Outputs:
    
    NULL
    
  2. ==============================

    2.unset은 실제로 함수가 아니라 언어 구조입니다. 반환이나 포함보다 더 이상 함수 호출이 아닙니다.

    unset은 실제로 함수가 아니라 언어 구조입니다. 반환이나 포함보다 더 이상 함수 호출이 아닙니다.

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

  3. ==============================

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

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

    이것은 개인적인 경험과 다른 사람들의 경험에서도 나온 것입니다. 여기서 unset () 함수의 주석을 참조하십시오.

    나는 개인적으로 루프에서 반복 사이에 unset ()을 사용하여 스택의 지연을 yo-yo 크기로 가질 필요가 없습니다. 데이터는 사라졌지만 풋 프린트는 남아 있습니다. 다음 반복에서 메모리는 이미 php에 의해 잡혀 있으므로 다음 변수를 더 빨리 초기화 할 수 있습니다.

  4. ==============================

    4.

    <?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 결과 :

    PHP 5.3 결과 :

    PHP 5.2 결과 :

    PHP 5.1 결과 :

    PHP 5.0 및 4.4에서는 상황이 다르게 보입니다.

    5.0:

    4.4:

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

  5. ==============================

    5.배열 요소와 다른 점이 있습니다.

    배열 요소와 다른 점이 있습니다.

    이 예제를 고려해보십시오.

    $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";
    

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

  6. ==============================

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

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

    $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
    
  7. ==============================

    7.객체, 특히 게으른로드 시나리오에서는 가비지 컬렉터가 유휴 CPU 사이클에서 실행되고 있다고 생각해야합니다. 따라서 많은 객체가 작은 시간의 페널티를로드 할 때 문제가 발생한다고 가정하면 메모리가 해제됩니다.

    객체, 특히 게으른로드 시나리오에서는 가비지 컬렉터가 유휴 CPU 사이클에서 실행되고 있다고 생각해야합니다. 따라서 많은 객체가 작은 시간의 페널티를로드 할 때 문제가 발생한다고 가정하면 메모리가 해제됩니다.

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

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

    PHP 버전에서 버전으로 바뀔 수있는 GC 동작에 따라 다릅니다. 하지만 그것은 PHP 5.3에서 잘 작동합니다.

    예. 이 샘플 (VirtueMart 2 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);
        ...
    
  8. ==============================

    8.나는 여전히 이것에 대해서는 의문 스럽지만 필자는 스크립트에서 시도해 보았고 xdebug를 사용하여 응용 프로그램 메모리 사용에 어떤 영향을 미치는지 알았습니다. 이 스크립트는 내 함수에서 다음과 같이 설정됩니다.

    나는 여전히 이것에 대해서는 의문 스럽지만 필자는 스크립트에서 시도해 보았고 xdebug를 사용하여 응용 프로그램 메모리 사용에 어떤 영향을 미치는지 알았습니다. 이 스크립트는 내 함수에서 다음과 같이 설정됩니다.

    function gen_table_data($serv, $coorp, $type, $showSql = FALSE, $table = 'ireg_idnts') {
        $sql = "SELECT COUNT(`operator`) `operator` FROM $table WHERE $serv = '$coorp'";
        if($showSql === FALSE) {
            $sql = mysql_query($sql) or die(mysql_error());
            $data = mysql_fetch_array($sql);
            return $data[0];
        } else echo $sql;
    }
    

    리턴 코드 바로 앞에 unset을 추가하면 160200이됩니다. $ sql = NULL로 변경하려고하면 다음과 같이 표시됩니다. 160224 :)

    하지만 unset () 또는 NULL을 사용하지 않을 때이 비교에서 독특한 점이 있습니다. xdebug는 160144를 메모리 사용량으로 사용합니다.

    그래서, unset ()이나 NULL을 사용하는 줄을주는 것이 여러분의 응용 프로그램에 프로세스를 추가 할 것이고 여러분의 코드에 기원을두고 가능한 한 효과적으로 사용하는 변수를 줄이는 것이 더 좋을 것이라고 생각합니다.

    내가 틀렸다면 정정 해줘. 고마워.

  9. ==============================

    9.unset과 null에 대한 새로운 성능 테스트를 만들었습니다. 주석에 언급 된 것처럼 여기에 쓰여진 것은 오류 (요소를 다시 작성)가 있기 때문입니다. 배열을 사용했는데, 지금은 중요하지 않습니다.

    unset과 null에 대한 새로운 성능 테스트를 만들었습니다. 주석에 언급 된 것처럼 여기에 쓰여진 것은 오류 (요소를 다시 작성)가 있기 때문입니다. 배열을 사용했는데, 지금은 중요하지 않습니다.

    <?php
    $arr1 = array();
    $arr2 = array();
    for ($i = 0; $i < 10000000; $i++) {
        $arr1[$i] = 'a';
        $arr2[$i] = 'a';
    }
    
    $start = microtime(true);
    for ($i = 0; $i < 10000000; $i++) {
        $arr1[$i] = null;
    }
    $elapsed = microtime(true) - $start;
    
    echo 'took '. $elapsed .'seconds<br>';
    
    $start = microtime(true);
    for ($i = 0; $i < 10000000; $i++) {
        unset($arr2[$i]);
    }
    $elapsed = microtime(true) - $start;
    
    echo 'took '. $elapsed .'seconds<br>';
    

    하지만 PHP 5.5.9 서버에서만 테스트 할 수 있습니다. 결과는 다음과 같습니다.  - 4.4571571350098 초 걸렸습니다.  - 4.4425978660583 초 걸렸습니다.

    나는 가독성을 이유로 설정되지 않은 것을 선호한다.

  10. ==============================

    10.즉석 메모리를 해제하지 않으면 unset 코드는 여전히 매우 유용하며 메소드를 종료하기 전에 코드 단계를 넘길 때마다이를 수행하는 것이 좋습니다. 즉각적인 기억을 풀어주는 것이 아니라 즉각적인 메모리는 CPU를위한 것이고, 2 차 메모리는 RAM입니다.

    즉석 메모리를 해제하지 않으면 unset 코드는 여전히 매우 유용하며 메소드를 종료하기 전에 코드 단계를 넘길 때마다이를 수행하는 것이 좋습니다. 즉각적인 기억을 풀어주는 것이 아니라 즉각적인 메모리는 CPU를위한 것이고, 2 차 메모리는 RAM입니다.

    이것은 또한 메모리 누수를 방지하는 방법에 대해서도 다루고 있습니다.

    이 링크를 참조하십시오. http://www.hackingwithphp.com/18/1/11/be-wary-of-garbage-collection-part-2

    나는 오랫동안 unset을 사용 해왔다.

    코드에서 이처럼 더 나은 연습을하면 배열로 이미 사용 된 모든 변수를 즉시 해제 할 수 있습니다.

    $data['tesst']='';
    $data['test2']='asdadsa';
    ....
    nth.
    

    그냥 unset ($ data); 모든 변수 사용을 해제합니다.

    관련 주제를 참조하십시오.

    PHP에서 변수를 설정 해제하는 것이 얼마나 중요합니까?

    [곤충]

  11. ==============================

    11.기록 및 소요 시간 제외 :

    기록 및 소요 시간 제외 :

    <?php
    echo "<hr>First:<br>";
    $x = str_repeat('x', 80000);
    echo memory_get_usage() . "<br>\n";      
    echo memory_get_peak_usage() . "<br>\n"; 
    echo "<hr>Unset:<br>";
    unset($x);
    $x = str_repeat('x', 80000);
    echo memory_get_usage() . "<br>\n";      
    echo memory_get_peak_usage() . "<br>\n"; 
    echo "<hr>Null:<br>";
    $x=null;
    $x = str_repeat('x', 80000);
    echo memory_get_usage() . "<br>\n";      
    echo memory_get_peak_usage() . "<br>\n";
    
    echo "<hr>function:<br>";
    function test() {
        $x = str_repeat('x', 80000);
    }
    echo memory_get_usage() . "<br>\n";      
    echo memory_get_peak_usage() . "<br>\n"; 
    
    echo "<hr>Reasign:<br>";
    $x = str_repeat('x', 80000);
    echo memory_get_usage() . "<br>\n";      
    echo memory_get_peak_usage() . "<br>\n"; 
    

    그것은

    First:
    438296
    438352
    Unset:
    438296
    438352
    Null:
    438296
    438352
    function:
    438296
    438352
    Reasign:
    438296
    520216 <-- double usage.
    

    결론, null과 unset free 메모리 모두 예상대로 (실행 종료시뿐만 아니라). 또한 변수를 재 할당하면 어떤 지점에서 값이 두 번 유지됩니다 (520216 대 438352)

  12. ==============================

    12.PHP 7은 이미 이러한 메모리 관리 문제에 대해 연구되었으며 최소한의 사용으로 축소되었습니다.

    PHP 7은 이미 이러한 메모리 관리 문제에 대해 연구되었으며 최소한의 사용으로 축소되었습니다.

    <?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";
    
    ?>
    

    PHP 7.1 출력 :

    0.16778993606567 초 걸렸습니다. 0.16630101203918 초가 걸렸습니다.

  13. from https://stackoverflow.com/questions/584960/whats-better-at-freeing-memory-with-php-unset-or-var-null by cc-by-sa and MIT license