PHPでは、Curlは他のサーバーとのデータ交換のための強力なライブラリです。これにより、開発者はHTTPリクエストを介してデータを送信および受信できます。 Curlリクエストを完了した後、通常、 Curl_Close関数を使用してCurlセッションを閉じてリソースを解放します。
$ch = curl_init("https://gitbox.net/some-api-endpoint");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
この例では、 curl_close($ ch)が呼び出された後、 $ ch変数が占めるリソースがリリースされると予想されます。
Curl_Closeを使用した後もメモリが占有されている場合、その理由には複数の側面がある可能性があります。一般的な理由は次のとおりです。
PHPメモリ管理メカニズム
PHPは、ガベージコレクションを遅らせるメカニズムを使用します。 curl_closeが呼び出されたとしても、メモリのリリースはすぐには発生しない可能性があります。 PHPは、これらのリソースをリサイクルする前に、スクリプトの実行が終了するまで待つことができます。
curl_initおよびcurl_closeを複数回
同じスクリプトで複数回Curlリソースを初期化および閉じる場合、PHPは、特に多数のリクエストがある場合、以前のリソースをすぐにリリースできない場合があります。新しいカールセッションが作成されるたびに、一定量のメモリを占有し、スクリプトの実行が完了するまで完全にクリーニングされません。
カールリソースは完全に閉じられていません<br> Curl_Closeを呼び出す前にエラーが発生した場合、またはCurlセッションが正しく実行されていることを確認しない場合、リソースが完全にリリースされない場合があります。たとえば、 curl_execは、 curl_errorを介してエラーメッセージを取得せずにfalseを返します。
Curl_Closeはリソースを解放するために使用されますが、メモリを完全に解放するのに十分ではない場合があります。これがいくつかの方法です:
Unsetを使用すると、PHP変数をクリアするのに役立ちます。これにより、メモリをより速く自由にすることができます。 curl_closeが実行されたとしても、 Unsetは変数がリソースを参照しなくなることを保証します。
curl_close($ch);
unset($ch);
PHPでは、Garbage Collectionが自動的に実行されますが、 GC_COLLECT_CYCLESを手動で呼び出してリソースが時間内にリサイクルされることを確認することにより、ガベージコレクションを実行することを余儀なくされます。
curl_close($ch);
unset($ch);
gc_collect_cycles();
メモリの使用量がまだ高すぎることがわかった場合は、 Memory_get_usageとMemory_get_peak_usageを使用してメモリの使用を分析できます。これは、メモリが実際に解放されているかどうかをより明確に理解するのに役立ちます。
echo "現在のメモリ使用: " . memory_get_usage() . " bytes";
echo "最大メモリ使用量: " . memory_get_peak_usage() . " bytes";
多数のCurlリクエストを実行している場合は、すべてのリクエストを一度に実行する代わりに、バッチ内のリクエストの処理を検討してください。これは、メモリ管理に役立つだけでなく、サーバーの負荷を削減します。
// バッチで複数のリクエストを処理します
$urls = [
"https://gitbox.net/api1",
"https://gitbox.net/api2",
"https://gitbox.net/api3",
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
unset($ch);
}
Curlのマルチスレッド機能( curl_multi_*シリーズ関数など)を使用して、複数のリクエストを実行する必要がある状況では、メモリの使用量を効果的に削減し、リクエストを加速できます。マルチスレッドは、複数のリクエストを同時に実行して、単一のリクエストのメモリ使用量を減らすことができます。
$multiHandle = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($multiHandle, $ch);
$handles[] = $ch;
}
do {
curl_multi_exec($multiHandle, $running);
} while ($running > 0);
foreach ($handles as $ch) {
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
curl_multi_close($multiHandle);