検索
ホームページバックエンド開発PHPチュートリアルPHP 関数の実行時にメモリが解放されないのはなぜですか?

最近、必要な構造化データを取得するためにファイルを処理する必要があったため、大きなファイルをインポートしていました。
大量のデータを配列に保存します。
処理中に大量のメモリが消費されますが、memory_limit の設定を十分に大きくしておけば問題ありません。
処理の過程で不要な項目の設定も解除します。ただし、me​​mory_get_usage() は関数呼び出しの前後でメモリ比較を出力します。
関数呼び出し後、メモリが大幅に減少していないことがわかりました。これらの大きな配列は設定解除されています。も同じです。
インポートされたファイルの量が多くない場合、メモリ オーバーフローのエラー メッセージは表示されません。ただし、ファイルが十分に大きい場合。実行中、
関数が呼び出された後も、メモリは依然として多くのスペースを占有します。そしてメモリオーバーフローを引き起こします。
これを見ると少し憂鬱になります。関数呼び出し後にローカル変数の空間が解放されていませんか?
メモリリークですか? 同じ問題に遭遇した人はいますか?誰かが同じ問題に遭遇したか、それについて知っていることを願っています。一緒に話し合いましょう。ありがとう。
ps: スコアはかなり小さいので、それだけです。


ディスカッションへの返信 (解決策)

unset() は配列ですか、それとも配列要素ですか?

また、関数で使用される配列はローカル変数ですか、それともグローバル変数ですか?

また、関数で使用される配列はローカル変数ですか、それともグローバル変数ですか?
さて、私はこれらすべてを検討しました
unset は配列です
関数内の unset() グローバル変数も知っています
関数内の一時変数を削除するだけです
グローバル $GLOBALS 変数も設定解除しました
まだ同じです
これまでにこれほど大きなデータを処理したことがなかったため、同様の問題が発生しましたか?
このような問題に遭遇した今、この問題について改めて考えさせられます。
今日は PHP のメモリ管理の原則についても見ていきました

コードに遭遇した人がいるかどうかはわかりません。 。 。

コード。 。 。
コードが長すぎるので、関数を投稿します

function importTestSuiteFormArray1($db,$parentID,$tproject_id,$userID,$duplicateLogic,&$testsuiteArray,&$testcaseArray){	global $productIndex;	$unexistPF = array();//用于存放当前项目中没有的excel文件存在的平台	$produceRelFB = array();	$resultMap = null;	$tsResult = null;//测试套件导入结果	$tables = tlObject::getDBTables("platforms");	$pfSql = " select id,name from ".$tables['platforms']." where testproject_id=$tproject_id";	$pfRe = $db->fetchColumnsIntoMap($pfSql,"id","name");	$pfRe = is_null($pfRe) ? array() : $pfRe;	foreach($productIndex as $vKey=>$pItem){		if(!in_array($vKey, $pfRe)){			$unexistPF[] = $vKey;		}	}//	$memory1 = memory_get_usage();//	$fileName = date("md-His");//	$hand = fopen("e:/testcase/".$fileName.".txt","a+");//	$bTime = microtime_float();	$tempTSArray = array();	$createSuc = "创建成功。";	$updateSuc = "更新成功。";	if(is_array($testsuiteArray) && count($testsuiteArray)>0){		foreach($testsuiteArray as $key=>$tsItem){//			$begin = microtime_float();			if ($tsItem['name'] != "")			{				if($tsItem['parentNum']==0){					$parID = $parentID;				}else{					$parID = $tempTSArray[$key]['parentID'];				}				$tsuiteMgr = new testsuite($db);				$info = $tsuiteMgr->get_by_name($tsItem['name'],$parID);				if( is_null($info) )				{					$ret = $tsuiteMgr->create($parID,$tsItem['name'],"",$tsItem['node_order']);					$tsuiteID = $ret['id'];					$tsResult[] = array($tsItem['name'],$createSuc);									}				else				{					$tsuiteID = $info[0]['id'];					$ret = $tsuiteMgr->update($tsuiteID,$tsItem['name'],"",null,$tsItem['node_order']);					$tsResult[] = array($tsItem['name'],$updateSuc);				}				if(is_array($tsItem['children']) && count($tsItem['children'])>0){					foreach($tsItem['children'] as $val){						$tempTSArray[$val]['parentID'] = $tsuiteID;					}				}								}//			$end = microtime_float();//			fwrite($hand, "每条规约用时:".($end-$begin)."\r\n");			}	}//	echo "testsuiteArray前".memory_get_usage()."<br>";	$testsuiteArray = null;//	echo "testsuiteArray后".memory_get_usage()."<br>";	$GLOBALS['testsuiteArray']=null;//	echo "全局testsuiteArray后".memory_get_usage()."<br>";	if(is_array($testcaseArray) && count($testcaseArray)>0){		$tcData = array();//		$begin = microtime_float();		$flag = 0;		foreach ($testcaseArray as $key=>$tsItem){			if($tsItem['parentNum']==0){				$parID = $parentID;			}else{				$parID = $tempTSArray[$key]['parentID'];			}			$tcData[$flag] = array(								"name"=>$tsItem['name'],								"node_order"=>$tsItem['order'],								"parentID"=>$parID			) ;			if(is_array($tsItem['property']) && count($tsItem['property'])>0){				foreach($tsItem['property'] as $pKey=>$val){					$tcData[$flag][$pKey] = $val;				}			}			if(is_array($tsItem['custom_fields']) && count($tsItem['custom_fields'])>0){				foreach($tsItem['custom_fields'] as $cfName=>$cfValue){					$tcData[$flag][customfields][] = array("name"=>$cfName,"value"=>$cfValue);				}			}			if(is_array($tsItem['srs']) && count($tsItem['srs'])>0){				$tcData[$flag]['srs'] = $tsItem['srs'];			}			if(is_array($tsItem['produce']) && count($tsItem['produce'])>0){				$tcData[$flag]['produce'] = $tsItem['produce'];			}			$flag++;		}//		$end = microtime_float();//		fwrite($hand, "循环用例时间:".($end-$begin)."\r\n");//		echo "testcaseArray前".memory_get_usage()."<br>";		$testcaseArray = null;//		echo "testcaseArray后".memory_get_usage()."<br>";		$GLOBALS['testcaseArray']=null;//		echo "全局testcaseArray后".memory_get_usage()."<br>";		$tempTSArray = null;//		echo "tempTSArray后".memory_get_usage()."<br>";		if(is_array($tcData) && count($tcData)>0){//			$begin = microtime_float();			$resultMap = saveImportedTCData1($db,$tcData,$tproject_id,$userID,null,$duplicateLogic,$produceRelFB,$pfRe);			$tcData = null;//			echo "tcData后".memory_get_usage()."<br>";//			$memory2 = memory_get_usage();//			$end = microtime_float();//			fwrite($hand, "保存用例总时间:".($end-$begin)."\r\n");//			fwrite($hand, "总用时:".($end-$bTime)."\r\n");//			fwrite($hand, "内存消耗:".($memory2-$memory1)."\r\n");		}	}										$return = array("resultMap"=>$resultMap,"tsResult"=>$tsResult,"unexistPF"=>$unexistPF,"produceRel"=>$produceRelFB);	return $return;//	return $resultMap;	}

説明しましょう: $testsuiteArray と $testcaseArray は、ファイルを解析して得られる配列です。 2 つのアレイのサイズは数十 M または数百 M になる場合があります。
問題は配列が大きすぎることではなく、他の方法も使用できます。問題は、この関数とこの関数内の save ImportTCData1 関数を呼び出した後、save ImportTCData1 を呼び出した後もメモリが大幅に減少しないことです。返された結果と参照された変数をすべて破棄しようとしましたが、それでもメモリが大量に占有され、最終的にはオーバーフローが発生しました。このようなコードを読むのはおそらく非常に疲れるでしょう、ありがとう。

誰もいない。 。 。

を参照できます
http://www.laruence.com/2011/03/04/1894.html

を参照できます
http://www.laruence.com/2011/03/04/1894 .html
はは、ブロガーの発言を読んで勉強しました。
シンボルテーブルによって占有されていると言われました。次に、シンボルテーブルを解放する方法を知りたいです。
そのブロガーに質問です。ご返信ありがとうございます

ファイル分析後、配列は 20M を占有します
次に、データベース操作があり、これには多くの操作が含まれます。
実行後、メモリは初期よりも 1G 近く増加しています
この結果に何か異常はありますか?
処理の過程で不要なデータの設定が解除されました。

実際、注意深く分析した結果、
それらの配列は呼び出し後に解放されます。
では、なぜ通話が完了した後にこれほど多くのメモリを占有するのでしょうか?
データベース操作が重いためですか?
- -

質問したいのですが、3Q

5000 配列、各配列にはより多くの情報が含まれています。
17W を超えるデータベース操作を実行し、データベース実行時間は 40 秒を超えました
ループ操作を使用しました。
各配列演算のメモリは徐々に増加します。
論理的に言えば、各ループで使用されるローカル変数は同じです。
データベースの操作結果を格納する配列のみが増加していますが、増加量はわずかです。
そんなに多くのメモリを必要とするのは不可能です。
では、この余分なメモリ使用量はどこから来るのでしょうか?
関数が呼び出されるまで。これらのメモリ空間は解放されません。なぜですか?
なぜ?なぜ?なぜ?
このボトルネックにとても悩んでいます。

経験豊富
非常に熟練した兄弟や叔父
余分な記憶力はどこから来たのですか?
助けて。 。 。 。 。

データベース接続を解放してみてください。データベース操作によって占有されている可能性があります。

データベース接続を解放してみてください。データベース操作によって占有されている可能性があります。
リリースされるデータベースについても同様です。
この中間操作によりメモリ リークが発生しましたか?
この状況に遭遇した人はいますか?

我以前碰到过的情况是create_function有内存泄漏,但你这里没有用

这个大概只能自己慢慢调了,
你装xdebug里面有几个功能可以帮助分析内存

我要炸了- -
想太多了 

你需要检查一下承载返回值的 $return 所占的空间

你需要检查一下承载返回值的 $return 所占的空间
返回值 $return 被unset了
还是占用很大

$resultMap=saveImportedTCData1($db,$tcData,$tproject_id,$userID,null,$duplicateLogic,$produceRelFB,$pfRe);

在这个函数调用前后的内存差别很大。
我把返回结果$resultMap,$tcData,和$produceRelFB等有关联的数据都unset,还是一样。
函数调用完不是释放完它执行时所分配的所有临时空间吗。怎么会这样子。想不通啊。那块内存哪去了?where are you- -

你去看下php的垃圾回收机制吧。

你去看下php的垃圾回收机制吧。
这个早在我是学生时代就了解java gc
php gc也早就了解了跟java很像的机制。
我现在是觉得不是这些问题
我觉得应该深入php内核 研究下php内存分配机制

使用xdebug 只有执行实现 没有内存情况
我用WinCacheGrind .exe 查看的
还是我没找到- -

如果没有处理过这样大的数据
跟这么多次的数据库操作
在一般系统上还碰不到这些问题
这样功能到不是会常用
但是作为一个管理工具 
有时候就是要执行这么几次大数据的处理 
我想这个东西解决了 
应该又是一次成长 会更加注意效率 还有其他问题
一定要解决
感觉好孤单 一个人自言自语- -

你的这个函数中还调用了其他自定义函数,也还实例化了自定义类,这些都有可能产生问题
你得一个一个排查

那就检查一下这个函数saveImportedTCData1,看看是不是因为他内部的问题
另外如果是从数据库中获取数据,记录集资源有没有被释放……

谢谢楼上两位回答。
自定义类 还有函数没错
其实最大问题saveImportedTCData1 在这个函数。
我把这个函数产生的所有输出都给释放掉了了。
即使是释放完了 通过meomory_get_usage()输出的内存占用依然是调用这个函数之前内存调用的n倍
大概多了一个数量级。
我看我还是检查下这个函数
话说xdebug 能通过WinCacheGrind  查看内存消耗吗
我没看到有查看内存的 

再次向回答人说谢谢
ps:其实如果百度跟谷歌能找到我要的答案我一般不会问。我发现我问的问题大多数没有得到想要答案。能跟大家交流沟通也学习很多。再努力找原因。

?????。

自己排查吧,这个外人真帮不上什么忙,特别是你的saveImportedTCData1怎么写的都不知道。
加下引用传递再测试一下,可能是因为你函数里有一次变量分离的,而变量本身又很大的缘故。
$resultMap=saveImportedTCData1($db, &$tcData,$tproject_id,$userID,null,$duplicateLogic, &$produceRelFB,$pfRe);

自己排查吧,这个外人真帮不上什么忙,特别是你的saveImportedTCData1怎么写的都不知道。
加下引用传递再测试一下,可能是因为你函数里有一次变量分离的,而变量本身又很大的缘故。
$resultMap=saveImportedTCData1($db,&$tcData,$tproject_id,$userID,null,$duplicateLogic,&$produc……
恩 我的那个函数原型是刚好在$tcData,和$produceRelFB 有引用

刚才检查了一下
上面那个函数中有行代码

  $tcData[$flag][customfields][] = array("name"=>$cfName,"value"=>$cfValue);

[customfields]忘了加引号,我记得曾经看手册有提到这个问题,这个会导致效率很低。
因为php要额外很多检查。所以一直都是习惯加引号。可能不小心给忘了。
结果因为大量数据 所以一下子开销差别就出来,我算了下空间开销差了二十倍。时间开销没算。
问题还没解决还在找另一个函数出现的问题。

经过xdebug 再调试分析
最终问题得以解决

谢谢以上所有朋友

そのポスターに感心します

しかし、ポスターはそれをどうやって解決したのでしょうか?私も最近このような問題に遭遇しました。解決策を探していますか?

問題の主な原因は、元の投稿者にありました。
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
PHPの目的:動的なWebサイトの構築PHPの目的:動的なWebサイトの構築Apr 15, 2025 am 12:18 AM

PHPは動的なWebサイトを構築するために使用され、そのコア関数には次のものが含まれます。1。データベースに接続することにより、動的コンテンツを生成し、リアルタイムでWebページを生成します。 2。ユーザーのインタラクションを処理し、提出をフォームし、入力を確認し、操作に応答します。 3.セッションとユーザー認証を管理して、パーソナライズされたエクスペリエンスを提供します。 4.パフォーマンスを最適化し、ベストプラクティスに従って、ウェブサイトの効率とセキュリティを改善します。

PHP:データベースとサーバー側のロジックの処理PHP:データベースとサーバー側のロジックの処理Apr 15, 2025 am 12:15 AM

PHPはMySQLIおよびPDO拡張機能を使用して、データベース操作とサーバー側のロジック処理で対話し、セッション管理などの関数を介してサーバー側のロジックを処理します。 1)MySQLIまたはPDOを使用してデータベースに接続し、SQLクエリを実行します。 2)セッション管理およびその他の機能を通じて、HTTPリクエストとユーザーステータスを処理します。 3)トランザクションを使用して、データベース操作の原子性を確保します。 4)SQLインジェクションを防ぎ、例外処理とデバッグの閉鎖接続を使用します。 5)インデックスとキャッシュを通じてパフォーマンスを最適化し、読みやすいコードを書き、エラー処理を実行します。

PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO)PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO)Apr 15, 2025 am 12:15 AM

PHPで前処理ステートメントとPDOを使用すると、SQL注入攻撃を効果的に防ぐことができます。 1)PDOを使用してデータベースに接続し、エラーモードを設定します。 2)準備方法を使用して前処理ステートメントを作成し、プレースホルダーを使用してデータを渡し、メソッドを実行します。 3)結果のクエリを処理し、コードのセキュリティとパフォーマンスを確保します。

PHPおよびPython:コードの例と比較PHPおよびPython:コードの例と比較Apr 15, 2025 am 12:07 AM

PHPとPythonには独自の利点と短所があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1.PHPは、大規模なWebアプリケーションの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンスと機械学習の分野を支配しています。

アクション中のPHP:実際の例とアプリケーションアクション中のPHP:実際の例とアプリケーションApr 14, 2025 am 12:19 AM

PHPは、電子商取引、コンテンツ管理システム、API開発で広く使用されています。 1)eコマース:ショッピングカート機能と支払い処理に使用。 2)コンテンツ管理システム:動的コンテンツの生成とユーザー管理に使用されます。 3)API開発:RESTFUL API開発とAPIセキュリティに使用されます。パフォーマンスの最適化とベストプラクティスを通じて、PHPアプリケーションの効率と保守性が向上します。

PHP:インタラクティブなWebコンテンツを簡単に作成しますPHP:インタラクティブなWebコンテンツを簡単に作成しますApr 14, 2025 am 12:15 AM

PHPにより、インタラクティブなWebコンテンツを簡単に作成できます。 1)HTMLを埋め込んでコンテンツを動的に生成し、ユーザー入力またはデータベースデータに基づいてリアルタイムで表示します。 2)プロセスフォームの提出と動的出力を生成して、XSSを防ぐためにHTMLSPECIALCHARSを使用していることを確認します。 3)MySQLを使用してユーザー登録システムを作成し、Password_HashおよびPreprocessingステートメントを使用してセキュリティを強化します。これらの手法を習得すると、Web開発の効率が向上します。

PHPとPython:2つの一般的なプログラミング言語を比較しますPHPとPython:2つの一般的なプログラミング言語を比較しますApr 14, 2025 am 12:13 AM

PHPとPythonにはそれぞれ独自の利点があり、プロジェクトの要件に従って選択します。 1.PHPは、特にWebサイトの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンス、機械学習、人工知能に適しており、簡潔な構文を備えており、初心者に適しています。

PHPの永続的な関連性:それはまだ生きていますか?PHPの永続的な関連性:それはまだ生きていますか?Apr 14, 2025 am 12:12 AM

PHPは依然として動的であり、現代のプログラミングの分野で重要な位置を占めています。 1)PHPのシンプルさと強力なコミュニティサポートにより、Web開発で広く使用されています。 2)その柔軟性と安定性により、Webフォーム、データベース操作、ファイル処理の処理において顕著になります。 3)PHPは、初心者や経験豊富な開発者に適した、常に進化し、最適化しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、