PHP 開発では、大きな配列を扱うときにメモリの問題が発生しやすくなります。この記事では、array_diff アルゴリズムを使用して巨大な配列の差分を解決する方法について説明します。さらに、大規模な配列を操作するときにさまざまなメモリ管理手法を使用してパフォーマンスを最適化する方法を学びます。
1. 問題の説明
シナリオを考えてみましょう: 2 つの配列があり、どちらも非常に大きく、各配列には 100,000 個の要素があります。ここで、これら 2 つの配列の違いを見つけたいと思います。簡単に言えば、配列内にのみ存在する要素を見つけることです。コードの実装は次のとおりです。
<?php $array1 = array(); $array2 = array(); // 初始化数组1,2,每个数组都有 10 万个元素 for($i=0;$i<1000000;$i++){ $array1[$i] = $i; $array2[$i] = $i+1; } // 计算差集 $result = array_diff($array1, $array2); print_r($result); ?>
上記のコードを実行すると、ページがすぐに応答しなくなり、PHP スクリプトが割り当て可能なメモリを使い果たしたというエラーが報告されます。これは、PHP のデフォルトのメモリ制限が 128MB であり、大きな配列を処理するには十分な大きさではないためです。したがって、この問題を解決するには、最適化アルゴリズムまたはその他のメモリ管理手法を考慮する必要があります。
2. 最適化アルゴリズム
配列内の要素がすでに順番に配置されている場合は、カーソルを使用して検索を高速化し、実行時間とメモリ使用量を削減できます。コードの実装は次のとおりです。
<?php $array1 = array(); $array2 = array(); // 初始化数组1,2,每个数组都有 10 万个元素 for($i=0;$i<1000000;$i++){ $array1[$i] = $i; $array2[$i] = $i+1; } // 排序数组1、2 sort($array1); sort($array2); // 初始化游标 $cursor1 = $cursor2 = 0; // 计算差集 $result = array(); while($cursor1 < count($array1) && $cursor2 < count($array2)){ if($array1[$cursor1] < $array2[$cursor2]){ $result[] = $array1[$cursor1]; $cursor1++; } elseif($array1[$cursor1] > $array2[$cursor2]){ $cursor2++; } else{ $cursor1++; $cursor2++; } } // 将数组1中剩余的元素添加入结果数组 while($cursor1 < count($array1)){ $result[] = $array1[$cursor1]; $cursor1++; } print_r($result); ?>
上記のコードは、実行時間を最適化し、メモリの使用効率を高めます。ただし、配列が正しくない場合、このアルゴリズムは機能しません。
3. セグメント化された処理テクノロジを使用する
PHP では、大きな配列を処理するときに array_diff によって使用されるメモリ オーバーヘッドが非常に大きくなります。ただし、PHP のメモリ マネージャーは、メモリ割り当てごとにメモリ割り当てテーブルを維持します。このテーブルは、各メモリ割り当てのサイズと場所を検出します。したがって、セグメンテーション処理テクノロジを使用して、大きな配列を多数の小さなサブ配列に分割し、各サブ配列を個別に処理して、過剰なメモリ領域の占有を避けることができます。コードの実装は次のとおりです。
<?php $array1 = array(); $array2 = array(); // 初始化数组1,2,每个数组都有 10 万个元素 for($i=0;$i<1000000;$i++){ $array1[$i] = $i; $array2[$i] = $i+1; } // 分段,每段 10000 个元素 $chunkSize = 10000; $chunks1 = array_chunk($array1, $chunkSize); $chunks2 = array_chunk($array2, $chunkSize); // 计算差集 $result = array(); foreach($chunks1 as $chunk1){ $temp = array_diff($chunk1, array_merge(...$chunks2)); $result = array_merge($result,$temp); } print_r($result); ?>
上記のコードでは、配列をサイズ 10000 の多数のサブ配列に分割し、それらを chunks1 配列と chunks2 配列に格納します。次に、chunks1 をループし、array_diff を使用して各サブ配列と chunks2 の差を計算し、結果を $result 結果配列に追加します。最後に、$result を最終結果にマージします。
4. ジェネレーターを使用して走査アルゴリズムをシミュレートする
大規模な配列のメモリ問題を解決するもう 1 つの方法は、PHP のジェネレーターを使用して 2 つの配列間の差分を見つける走査をシミュレートすることです。 PHP のジェネレーターを使用すると、シーケンス全体をメモリ内に構築するのではなく、シーケンスから値を 1 つずつ生成できます。コードの実装は次のとおりです。
<?php $array1 = array(); $array2 = array(); // 初始化数组1,2,每个数组都有 10 万个元素 for($i=0;$i<1000000;$i++){ $array1[$i] = $i; $array2[$i] = $i+1; } // 计算差集 $result = array(); function diff($arr1, $arr2) { sort($arr1); sort($arr2); $i = $j = 0; while($i < count($arr1) && $j < count($arr2)) { if($arr1[$i] < $arr2[$j]) { yield $arr1[$i]; $i++; } elseif($arr1[$i] > $arr2[$j]){ $j++; } else{ $i++; $j++; } } while($i < count($arr1)) { yield $arr1[$i]; $i++; } } // 遍历 generator foreach (diff($array1, $array2) as $value) { $result[] = $value; } print_r($result); ?>
上記のコードでは、diff 関数を定義し、ジェネレーターを使用して配列差分セットの計算の走査をシミュレートします。このアルゴリズムは、サブ配列を順番にソートし、カーソル比較を使用して 2 つの配列間の差異を見つけることにより、使用するメモリと CPU 時間を削減します。
5. 概要
PHP 開発では、大きな配列を扱うときは、メモリを大量に消費し、メモリ オーバーフローを引き起こす可能性があるため、特に注意する必要があります。この記事では、大規模な配列の処理に使用できるアルゴリズムの最適化、区分的処理手法、ジェネレーターによるシミュレートされたトラバーサル アルゴリズムなどの手法を紹介しました。どの方法を選択するかは、要件と環境によって異なります。ニーズに応じて、さまざまな手法を使用してコードを最適化し、大規模な配列を扱うときのコードのパフォーマンスと保守性を向上させることができます。
以上がPHP は差分セットと大規模な配列メモリ オーバーフローを検出しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。