递归会导致内存使用é‡æ¿€å¢ž

时间:2014-01-27 11:01:58

标签: php memory-management recursion

function rec_func($x) {   
   echo $x;
   if ($x < 1000) {
      $x++;
      rec_func(&$x);
   }
}

è¿™ä¸æ˜¯å®žé™…的递归函数,我将用于我的PHP脚本。就åƒè¿™ä¸ªä¾‹å­ä¸€æ ·ï¼Œæˆ‘的真实函数完全正常,直到我开始检查它使用了多少内存。

如果我循环这个功能,比如100次,没有什么ä¸å¥½çš„事情å‘生。æ¯æ¬¡è¿­ä»£ä¸­ä½¿ç”¨çš„内存ä¿æŒä¸å˜ã€‚但是,如果我循环1000次以上,那么此功能将开始消耗比以å‰æ›´å¤šçš„内存,直到最åŽä¸€æ¬¡è¿­ä»£ã€‚

峰值的数é‡ä¼¼ä¹Žå–决于我给它的å˜é‡æœ‰å¤šå¤§ï¼Œä»¥åŠå®ƒç»åŽ†äº†å¤šå°‘次迭代,但我无法确定。这就是问题的开始。此功能将在1000次内开始消耗更多内存。然而,我的函数在1000次迭代中æ¯150次左å³æ‰§è¡Œä¸€æ¬¡ï¼Œæœ€ç³Ÿç³•çš„是MY函数å¯èƒ½éœ€è¦å¾ªçŽ¯æ¬¡æ•°ç”šè‡³æ›´å¤šæ¬¡ã€‚

这让我很好奇,因为显而易è§çš„事情是使用传统的循环(我已ç»å®Œæˆï¼‰ï¼Œä½†æˆ‘真的想è¦ç†è§£ä¸ºä»€ä¹ˆä¼šå‘生这ç§æƒ…况,以åŠæ˜¯å¦å¯ä»¥é¿å…。

P.S。请注æ„,我仅在第一次迭代中使用实å˜é‡ï¼Œå¹¶ä¸”å…¶åŽçš„所有迭代都使用引用,以ä¿ç•™å†…存。æå‰è°¢è°¢ã€‚

1 个答案:

答案 0 :(得分:0)

(如果我错了,请纠正我)。 我认为,它与你的PHP模å—内存处ç†æœ‰å…³ï¼šå®ƒåœ¨å¼€å§‹è¿è¡Œæ—¶ä¼šä¿ç•™ä¸€äº›å†…存(例如,如果它用作CGI,或者你从命令æ示符调用它)。

æ¯æ¬¡å¼€å§‹é€’归时,基本上都会åšä¸¤ä»¶äº‹ï¼š

在调用下一级递归之å‰ï¼Œå°†å½“å‰çŠ¶æ€ä¿å­˜åˆ°è°ƒç”¨å †æ ˆã€‚如果您没有使用引用进行æ“作,那么也å¯ä»¥ä½¿ç”¨å½“å‰å †æ ˆçŠ¶æ€æ“作å˜é‡æ•°æ®ã€‚åªè¦ä¿ç•™çš„内存足够,您的内存消耗就ä¸ä¼šå¢žåŠ ï¼Œä½†æ˜¯å½“内存ä¸è¶³æ—¶ï¼Œå°†ä¿ç•™ä¸€å †æ–°çš„内存,如果需è¦æ›´å¤šå†…存。 它æ„味ç€ä»¥ä¸‹å†…容:

function rec_func($x) {   
   echo $x;
   if ($x < 1000) {
      $x++;
      rec_func($x);
   }
}

这会有更大的内存使用é‡ï¼Œå› ä¸ºæ¯æ¬¡é€’å½’å‘生时,堆栈中都会有一个é¢å¤–的行,你将在内存中创建一个é¢å¤–çš„$ xæ¥å­˜å‚¨å®ƒçš„当å‰çŠ¶æ€ï¼Œä»¥ä¾¿ä¿ç•™é€’归返回当å‰å †æ ˆè°ƒç”¨æ—¶çš„值。

以下几行将消除内存使用问题 - 它使用å˜é‡å¼•ç”¨è¿›è¡Œæ“作(在这ç§æƒ…况下显然会破å功能:

function rec_func(&$x) {   
   echo $x;
   if ($x < 1000) {
      $x++;
      rec_func($x);
   }
}

(由于呼å«æ—¶å‚考传递,您的原始代ç ä¼šå¯¼è‡´è‡´å‘½é”™è¯¯ã€‚)

如果你想å‡å°‘内存使用é‡ï¼Œä½ åº”该(或者å¯ä»¥ï¼‰åœ¨å‡½æ•°å£°æ˜Žä¸­ä½¿ç”¨å¼•ç”¨ï¼Œè¿™äº›å¼•ç”¨åœ¨é€’归期间ä¸ä¼šæ”¹å˜ï¼Œä½†æ˜¯æ°¸è¿œä¸ä¼šå¯¹å˜é‡è¿›è¡Œæ”¹å˜ï¼ŒåŒæ—¶æ”¹å˜ã€‚

ä½ å¯ä»¥é€šè¿‡çŽ©debug_zval_dump()æ¥å°è¯•è‡ªå·±ï¼Œå°±åƒè¿™æ ·ï¼š

<?php
function rec_func_ref(&$x) {  
   //echo $x;
   if ($x < 100000) {
      $x++;
      rec_func_ref($x);
   }
  echo 'rec_func_ref:'.$x.'------<br />';
  debug_zval_dump($x);
  echo "<br />";
}

function rec_func_not_ref($x) {  
   //echo $x;
   if ($x < 100000) {
      $x++;
      rec_func_not_ref($x);
   }
  echo 'rec_func_not_ref:'.$x.'------<br />';
  debug_zval_dump($x);
  echo "<br />";
}


$a = 1;
rec_func_ref($a);
$a = 1;
rec_func_not_ref($a);
?>