以前にメモリの問題を解決したコードを調べるのに今日は丸一日かかりましたが、一度に 40,000 個のデータをインポートするコードの最適化プログラムに非常に不満を感じています。これでは根本的な解決にはならないと思います。オンライン検索を通じて、問題をさらに分析できます。
PHP のメモリ オーバーフローの問題では、最初の 2 つの方法については言及されません (エキスポの「About PHP Memory Release 問題」を参照することができます。難しいことではありません)。実際、問題の鍵は、一度メモリを解放するために何百回もループするのではなく、ループ内で同期的にメモリを解放する方法です。なぜなら、ループ内の再利用性の高いコードをカプセル化すると、デバッグ中にわかるからです。サブ関数を呼び出すと、プログラムの実行速度が数十倍低下します。この低下はデータ量によって異なります。
ネストされたループの形式で、大量のデータを含む配列を扱う場合、多くの場合、時間内にメモリを解放するために unset($a) が使用されますが、実際には、次の分析を引用します。エンジンでは、変数名とその値は実際には 2 つの異なる概念であり、値自体は名前のない zval* ストレージ (この場合は文字列値) であり、zend_hash_add() を通じて変数に割り当てられます。両方の変数名が同じ値を指している場合はどうなるでしょうか。
zval *helloval; ZVAL_STRING(helloval, "Hello World", 1); 、」 a", sizeof("a"), &helloval, sizeof(zval*), NULL);
zend_hash_add(EG(active_symbol_table), "b", sizeof("b"), &helloval, sizeof (zval*), NULL) ;
}
この時点で、実際に $a または $b を確認すると、両方に文字列「Hello World」が含まれていることがわかります。残念ながら、コードの 3 行目「unset($a)」を実行します。 ;" 現時点では、unset() は、$a 変数が指すデータが別の変数でも使用されていることを知らないため、単に盲目的にメモリを解放します。変数 $b へのアクセスは、メモリ領域が解放されたものとして解釈され、したがって、エンジンがクラッシュする原因になります
この問題は、zval の 4 番目のメンバー refcount (いくつかの形式があります) を利用して解決できます。変数が最初に作成されて割り当てられると、その refcount は 1 に初期化されると想定されます。コード スニペットが $b への helloval の割り当てを開始すると、その値が 2 に増加する必要があります。その結果、値は 2 つの変数によって参照されるようになります。
{
ZVAL_STRING(helloval, "Hello World", 1);
zend_hash_add (EG(active_symbol_table), "a", sizeof("a"); sizeof(zval*), NULL);
ZVAL_ADDREF(helloval);
zend_hash_add(EG(active_symbol_table), "b", sizeof("b "), &helloval, sizeof(zval*), NULL);ここで、unset() が元の変数の $a の対応するコピーを削除すると、特に refcount パラメータからそれがわかります。人間はこのデータに興味があるので、refcount をデクリメントして忘れるべきです。 "
要約すると、最も行う必要があるのは、実際にデータが最初に格納される配列を減らすことです。上記の例では、配列内の処理された要素はループ中に適時に解放されます。このようにしてループが続くと、メモリ使用量は変動し続けますが (メモリ再利用メカニズムの問題)、増加し続けるわけではありません。これにより、本来の目的は達成されますが、一度に処理できる最大データ量は依然として依存します。サーバーが PHP に割り当てるメモリ、一度に読み込まれる配列の量が制限を超えており、これについては神でも何もできません (笑)