Rumah >pembangunan bahagian belakang >masalah PHP >PHP menemui set perbezaan dan limpahan memori tatasusunan yang besar

PHP menemui set perbezaan dan limpahan memori tatasusunan yang besar

王林
王林asal
2023-05-22 19:27:06586semak imbas

Dalam pembangunan PHP, adalah mudah untuk menghadapi masalah ingatan apabila berurusan dengan tatasusunan yang besar. Artikel ini akan membincangkan cara menggunakan algoritma array_diff untuk menyelesaikan perbezaan tatasusunan yang besar. Selain itu, anda akan belajar cara menggunakan teknik pengurusan memori yang berbeza untuk mengoptimumkan prestasi apabila bekerja dengan tatasusunan yang besar.

1. Penerangan masalah

Pertimbangkan satu senario: terdapat dua tatasusunan, kedua-duanya sangat besar, setiap tatasusunan mempunyai 100,000 elemen. Sekarang kita ingin mencari perbezaan antara dua tatasusunan ini. Ringkasnya, ia adalah untuk mencari elemen yang hanya wujud dalam tatasusunan. Berikut ialah pelaksanaan kod:

<?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);
?>

Apabila kami menjalankan kod di atas, kami akan mendapati halaman tersebut menjadi tidak bertindak balas dengan cepat, dan kemudian ralat dilaporkan mengatakan bahawa skrip PHP kami telah kehabisan memori yang boleh diperuntukkan. Ini kerana had memori lalai PHP ialah 128MB, yang tidak cukup besar untuk mengendalikan tatasusunan yang besar. Oleh itu, algoritma pengoptimuman atau teknik pengurusan memori lain perlu dipertimbangkan untuk menyelesaikan masalah ini.

2. Algoritma Pengoptimuman

Jika elemen dalam tatasusunan sudah disusun mengikut tertib, anda boleh menggunakan kursor untuk mempercepatkan carian, yang boleh mengurangkan masa berjalan dan penggunaan memori. Berikut ialah pelaksanaan kod:

<?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);
?>

Kod di atas akan mengoptimumkan masa pelaksanaan dan menjadikan penggunaan memori lebih cekap. Walau bagaimanapun, jika tatasusunan tidak teratur, maka algoritma ini tidak akan berfungsi.

3. Gunakan teknologi pemprosesan bersegmen

Dalam PHP, array_diff menggunakan overhed memori yang sangat besar apabila memproses tatasusunan yang besar. Walau bagaimanapun, pengurus memori PHP mengekalkan jadual peruntukan memori untuk setiap peruntukan memori. Jadual ini mengesan saiz dan lokasi setiap peruntukan memori. Oleh itu, anda boleh menggunakan teknologi pemprosesan segmentasi untuk membahagikan tatasusunan besar kepada banyak sub-tatasusunan kecil, dan memproses setiap subtatasusunan secara berasingan untuk mengelakkan penggunaan ruang memori yang terlalu banyak. Berikut ialah pelaksanaan kod:

<?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);
?>

Dalam kod di atas, kami membahagikan tatasusunan kepada banyak sub-tatasusunan bersaiz 10000 dan menyimpannya dalam tatasusunan chunks1 dan chunks2. Kami kemudian menggelung ke atas chunks1, gunakan array_diff untuk mengira perbezaan antara setiap subarray dan chunks2, dan tambahkan keputusan pada $result results array. Akhirnya, kami menggabungkan $result ke dalam keputusan akhir.

4. Gunakan penjana untuk mensimulasikan algoritma traversal

Cara lain untuk menyelesaikan masalah memori tatasusunan besar ialah menggunakan penjana PHP untuk mensimulasikan traversal mencari perbezaan antara dua tatasusunan. Penjana PHP membolehkan anda menjana nilai daripada urutan satu demi satu, dan bukannya membina keseluruhan urutan dalam ingatan. Berikut ialah pelaksanaan kod:

<?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);
?>

Dalam kod di atas, kami mentakrifkan fungsi diff yang menggunakan penjana untuk mensimulasikan traversal mengira perbezaan tatasusunan. Algoritma ini menggunakan kurang memori dan masa CPU dengan mengisih subarray secara berurutan dan kemudian menggunakan perbandingan kursor untuk mencari perbezaan antara dua tatasusunan.

5. Ringkasan

Dalam pembangunan PHP, anda perlu berhati-hati apabila berurusan dengan tatasusunan yang besar, kerana ia mungkin mengambil terlalu banyak memori dan menyebabkan limpahan memori. Dalam artikel ini, kami memperkenalkan teknik seperti pengoptimuman algoritma, teknik pemprosesan piecewise dan algoritma traversal simulasi penjana yang boleh digunakan untuk memproses tatasusunan besar. Kaedah yang anda pilih bergantung pada keperluan dan persekitaran anda. Bergantung pada keperluan anda, anda boleh menggunakan teknik yang berbeza untuk mengoptimumkan kod anda untuk meningkatkan prestasi kod dan kebolehselenggaraan apabila berurusan dengan tatasusunan yang besar.

Atas ialah kandungan terperinci PHP menemui set perbezaan dan limpahan memori tatasusunan yang besar. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn