私の質問はどんどん長くなっているので、質問全体を書き直して、より短く短くすることにしました。
8GBのメモリを搭載した専用サーバーでWebサイトを実行しています。私はphp.ini設定のメモリ制限を上げる必要があることを完全に認識しています。 128Mから256Mに-1に設定しました。それでも問題は持続性です。
致命的なエラー:D:\ www\football\views\main.phpの81行目のメモリ不足(786432の割り当て)(24576バイトを割り当てようとしました)
メモリ不足は意味がありません。これは、786432バイトしか割り当てられておらず、さらに24576バイトが必要だからです。
786432バイトは768キロバイトで、かなり小さいです。
echo memory_get_peak_usage();
からこの番号を取得OS:Windows 2008 R2 64ビット
CPU:Intel Core i5-4コア
RAM:8 GB
Apache 2.2
PHP 5.3.1
ストレージ:2 x 1 TBハードドライブ
帯域幅:10 TB毎月
私はついに問題を調整して修正しました。改善のためにしたことをここで共有したいと思います。
favicon.ico
が欠落していたため、ルートエンジンが台無しになりました。ルートエンジンは非常に小さいですが、favicon.ico
を含めることで、ルートエンジンを実行しないことでメモリ使用量を削減できます。私のウェブサイトの大部分にそれがあり、この新しいセクションにそれを置くのを忘れました。Limit MaxRequestPerChild
が役立ちます。他の専用サーバーでは、MaxRequestPerChild
が制限されています。このサーバーでは、0に設定しました。各スクリプトは分離されていると常に考えていました。私のスクリプトの実行に800kbかかったとしましょう。 ApacheまたはPHPが完了すると、800kbのメモリが解放されます。この方法では機能しないようです。制限されたMaxRequestPerChild
は、制限されたMaxRequestPerChild
と古いプロセスが死んでいる後に新しいプロセスを作成することにより、メモリリークを防ぐのに役立ちます。これが私の新しい設定です。
ThreadsPerChild 1500
MaxRequestsPerChild 10000
ob_flush();
は、メモリをわずかに削減します。それはあまり役に立ちませんが、あらゆる最適化が役立ちます。
xdebug
を使用しました。私はそれが素晴らしいツールであると言わなければなりません、そして、私はそれがわずかにより速く動くようにいくつかのものを最適化しました。スワップを使用しようとすると、サーバーが死ぬという同じ種類の問題に遭遇しました。これは、mod_phpがメモリを解放しないためです。そのため、Apacheプロセスは、ApacheまたはPHPのメモリ制限に達するか、制限がない場合はサーバーをクラッシュさせて成長し続けます。
Apacheを再起動すると、新しい新しいスリムプロセスが生成されますが、PHPスクリプトを長期にわたって実行すると、問題が発生するまで成長します。
解決策は、一定数のクエリが提供された後、Apacheがプロセスを強制終了するようにして新しいクエリを作成することです( (それに関連するいくつかの質問 ) MaxRequestsPerChild 設定オプションを減らしますから、100(デフォルトは1000)としましょう。
もちろん、これにより、新しいプロセスを強制終了して生成するためにリソースが必要になりますが、少なくともサイトは機能し続けます。パフォーマンスを高く保つために実行中のプロセスの数を増やしたいと思うかもしれません。PHP(またはApache)メモリ制限x最大プロセス数がサーバーの物理RAMを超えないようにしてください。
これが私の経験です。
まず、memory_get_peak_usage()
はここでは役に立ちません。割り当てられたメモリの量のみを返しますが、それはエラーの原因となった同じ数です。
memory_get_usage
は、呼び出されたときに割り当てられているアクティブなメモリ量を返します。
ini_set('memory_limit', '256M');
は、システムメモリ上のPHPのフットプリントの最大許容値を設定します。 OOMを768Kで取得している場合、それをアップしても問題は解決しません。
使用しているPHPのバージョンについては示されていませんが、すぐにアップグレードすることをお勧めします。 ZendのMemory Managerがメモリの割り当て解除に失敗するバグがいくつかあり、まったく同じ問題につながる可能性があります。
ローカルサーバーと運用サーバーの両方で、同じバージョンのOS、同じ長いビット、同じバージョンのPHPが実行されていますか?答えはノーになります。
ウィンドウmalloc()
の問題とは無関係で、サブドメインであり、おそらくVirtualHost内にあり、768kのみを割り当てている場合、OSの問題のように聞こえます。
スクリプトにアクセスするときに、コマンドプロンプトからtasklist
を実行します。追加のApacheスレッド、またはプロセス全体のメモリ使用量の急増が見られますか?
最後のアイデアは、テーブルの行/列の各ループの後にflush()
やob_flush();
を実行することです。これにより、バッファがクリアされ、問題が発生している場合にメモリが節約されます。
一部のアプリケーションでは最大50%高速であるため、PHPを5.4+にアップグレードすることから始めます。多数のメモリリークを修正しました。 becnhamrksを参照してください: http://news.php.net/php.internals/5776
エラーはOut of memory
であり、Allowed memory size [..] exhausted
ではないことに注意してください。
そのため、メモリリークはシステムの他の場所にあります。 mysqlサーバーは、この重いクエリの後に大量のシステムメモリを使用し、Apache/phpを物理的およびスワップなしで残す可能性があります。
これは、常に同じ行で(および/または同じスクリプトで)エラーを説明するはずです。
Xdebugをインストールし、プロファイラートリガーを有効にします。プロファイラーファイルを生成し、問題の原因を特定できない場合はcachegrindファイルを投稿します。
編集:もちろんメモリリークが発生するページのプロファイラーファイル!
正しいphp.ini
を編集していないか、PHPやWebサーバーを再起動していないと思います。
<?php phpinfo();
の内容を含むphpinfo.php
ページをdocrootに作成して、正しいphp.ini
を変更していることを確認します。 Webサーバーが使用しているphp.ini
ファイルの場所に加えて、許可される最大スクリプトメモリも示します。
次に、ページにスタックトレースを追加して、これにつながった一連のイベントを確認できるようにします。次の関数は、致命的なエラーをキャッチし、何が起こったかについての詳細情報を提供します。
register_shutdown_function(function()
{
if($error = error_get_last())
{
// Should actually log this instead of printing out...
var_dump($error);
var_dump(debug_backtrace());
}
});
個人的には、Nginx + PHP-FPMは、Apacheを遅くしてから長年使ってきたものです。
ちょっと私も私のサーバーで同じ問題を抱えています。次のことを変更しました。
php.ini
を変更...
memory_limit = 128M
httpd.conf
に追加します
RLimitMEM 1073741824 2147483648
apacheを再起動してエラーを削除しました:
MySQLと開いている接続の数に問題がある可能性があります。そのため、数日ごとに再起動すると自動的に整理されます。スクリプトのシャットダウン時に自動的に閉じますか?
要約すると(元の質問からかなり離れたところにこの回答を追加しています):
これらがすべて有効な場合、考えられる唯一の説明は、6Gbがvery断片化されているということです-これは少し考えにくいと思います。 ApacheからPHPを呼び出す方法-mod_phpを言わなかった? fpm? Fcgi?
上記の各述語、特に空きメモリの述語を調べることから始めます。 6Gbの空きがあることをどのようにして知りますかエラーが発生したとき?より可能性の高い原因は、あなたが発見していないメモリリークが発生していることです。
Apacheの構成方法の詳細は提供していません。また、MaxRequestsPerChildとMaxMemFreeを減らすことも検討しました。 (これはスレッドごとに適用されるワーカーApacheにはあまり馴染みがありません-実際にはプロセスごとに制限が必要です)。 Apache構成からコア設定を提供した場合、さらに提案を行うことができます。
Ajaxを広範囲に使用している場合を除き、キープアライブ時間が2以下であることを確認してください。
致命的なエラー:メモリ不足(割り当て済みSOLVED
iも同様の問題を抱えており、何ヶ月も解決策がありませんでした。最後に、Apacheフォルダの1つ(つまり\ Apache\conf\extra)をチェックインしていましたが、Apacheのメモリ割り当てを制御するこのファイルに遭遇しました。ファイル名はhttpd-mpmです。このファイルでは、2048に設定されているMaxMemFreeを増やして、最初のMaxMemFree(IfModule!mpm_netware_module)で10000に設定してから2番目の5000個のIfModule mpm_netware_moduleのMaxMemFree。
これらは私の問題を解決しました。それが役に立てば幸い
これは数日前に私に起こりました。新たにインストールしたのですが、それでも起こりました。誰もが見ている限り、サーバーの仕様に基づいています。ほとんどの場合、無限ループです。 PHPコード自体ではなく、Apacheへのリクエストにある可能性があります。
このURLにアクセスしたときに言うことができますhttp:// localhost/mysite/page_with_multiple_requests
Apacheが複数のリクエストを受信した場合は、Apacheのアクセスログを確認してください。その要求をトレースし、システムに「ボトルネック」を引き起こす可能性のあるコードをチェックアウトします(sendmailを使用する場合の私のexec())。話しているボトルネックは「無限ループ」である必要はありません。終了するまでに時間がかかる関数である可能性があります。または、PHPのいくつかの「 プログラム実行関数 」
Ajaxリクエスト(ページの読み込み時に実行されるリクエスト)もチェックする必要があるかもしれません。そのajaxリクエストが同じURLにリダイレクトする場合
例えばhttpx:// localhost/mysite/page_with_multiple_requests
リクエストをもう一度やり直します
ランダムな行や、スクリプトが終了するコード自体を投稿すると、「ループ」コードがどこかにある可能性があります。 imho phpは、ランダムな行を無料で呼び出すだけではありません。
http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/
PHPでも同様の問題が発生しました。
1)エラーログを確認します。続行する前にすべてのエラーを取り除きます。 2)未使用のモジュールを削除するためにApache構成を変更することを検討してください-これはPHPが必要とするフットプリントを削減します-これに対する素晴らしいリンクがあります-Wordpressに固有ですが、それでも非常に便利です http://thethemefoundry.com/blog/optimize-Apache-wordpress/
私が見つけたバグの種類のアイデアを与えるために、Facebookにコンテンツを投稿しようとするコードがあり、FacebookがAPIを変更してこれが壊れたので、基本的に再試行を続けることを意味する「コンテンツエクスピレーター」を使用しましたこのコンテンツをFacebookに投稿し、大量のオブジェクトをメモリに残します。
Fcgidでphpを実行してみてください。これが役立つ場合があります。
これらは、ApacheモジュールとしてPHPを実行したときに表示される典型的なエラーです。私たちはこれらのエラーに何ヶ月も苦労しました。 mod_fcgid経由でPHPを使用するように切り替えると(Jamesが推奨しているように)、これらの問題はすべて修正されます。最新のVisual C++再頒布可能パッケージがインストールされていることを確認してください。
http://support.Microsoft.com/kb/2019667
また、MySQLの64ビットバージョンに切り替えることをお勧めします。 32ビットバージョンを実行する本当の理由はもうありません。
プロファイラーの出力ファイルから、私はあまり好きではない/信頼していないいくつかのことに気づき、これらを調べます:
異常を検出するための出力番号の意味や、PHPスクリプトの動作を知らないことは別として...、これは問題ではないでしょうか?同じmain.phファイルにインクルードがあると、これは再帰的なもののように見えますか?
2121 fl=D:\www\football\views\main.php
2122 fn=include::D:\www\football\views\main.php
ファイルD:\www\football\views\main.php
はいくつかの文字列関数を数回使用していることに注意してください。クエリによって返されたデータに対してこれらの関数を呼び出していると思います。
strlen
substr
strtotime
C言語のように、これらの関数がメモリの問題を回避するために文字列をnull
終端するか、文字列の終端の終端を必要とする場合、クエリによって返される文字列を調べます。
ウェブサイトのURLを投稿できますか?
ほとんどの場合、このようなエラーが発生する場合、問題はコードにあります。私はあなたが悪いコードを書いていると言っているのではなく、この量のメモリを使用しているものを注意深く観察する必要があると言っているのです。
常に「PHPのガベージコレクションはかなり悪い」を覚えておいてください。これはJavaや他の言語とは異なります。 gc_collect_cycleを使用してガベージコレクションを強制する方法がありますが、私の個人的な意見では、それはあなたの問題を解決しません。 PHPリクエスト/レスポンスサイクルが完了すると、ページの実行に使用されるすべてのメモリが解放されるため、バックグラウンドスクリプト(ギアマンなど)のようにスクリプトが長時間実行されると、メモリの問題が発生する可能性があります。スクリプトが実行されるまでメモリは解放されません。
上記がscr、ptに当てはまらず、非常に大量のメモリを必要とするコードがないと言った場合、問題はコード自体にあり、PHPは問題を解決しません。 Gearmanスクリプトの1つに一度直面したことがあり、1つの変数を配列の1つに追加するループの1つに問題がありました。変数自体は非常に重かった(約110KBのデータ)。したがって、コードを注意深く検査することをお勧めします。
派手な
これはPHP v 5.2 for Windowsの既知のバグであり、少なくともバージョン5.2.3に存在します。 https://bugs.php.net/bug.php?id=41615
提案された修正はどれも役に立たなかったため、PHPを更新する必要があります。
次の2つの事実は、間違いなくメモリリークを示しています。
最初にPDOを選び出し、他のすべての拡張機能を無効にして、Siege/Apache Bench(ab)などを使用して一晩実行します。 cli
インターフェイスを使用して実行することもできます(同じメモリ制限を維持するようにしてください)。
スクリプトの最後に memory_get_peak_usage()
関数を使用すると、PHPが使用していると考えているメモリ量を確認できます。
あなたのコメントからは800 kBですが、それで問題ありません。メモリ不足を引き起こす巨大なメモリ量ではありません;-)
最後に、現時点では5.4にアップグレードすることはお勧めしませんが、5.3.1以降に対処された複数の脆弱性とリークがあるため、おそらく最新の5.3.xにアップグレードする価値があります。
サーバーの物理メモリまたはスワップメモリが不足しているため、PHPは十分なメモリを割り当てることができません。
free
の出力をここに貼り付けられますか?
私の場合、このエラーは巨大な選択クエリ(何十万もの結果が返されたため)が原因で発生しました。
WordPressのスケーラビリティをテストするためにデータベースに数百万のレコードを追加した直後に発生したため、それが唯一の理由でした。