Można paginate swoje dane, fragment macierzy do pracy z mniejszych kawałków, a nawet zwiększyć memory_limit, ale załóżmy, że masz dużą tablicę i nie może zrobić inaczej.
Bawmy się więc z macierzą długości 1 000 000 i wypróbuj różne rozwiązania. Włożę zużycia pamięci pomiarów czasowych & obliczeniowych z mojego laptopa
obecne rozwiązanie (857MB/640ms)
for ($i=0; $i< 1000000; $i++){
$array[$i] = [
"key" => 'value',
"key2" => $i,
"key3" => $i/3
];
}
$map = array_map(function (array $item) {
$item['key4'] = 1;
$item['key5'] = 1;
$item['key6'] = 1;
return $item;
}, $array);
Z tego kawałka kodu zużycie pamięci na moim laptopie jest 857MB i czas obliczeniowej 640ms.
W tym przykładzie tworzysz zupełnie nową zmienną $map
ze swojej $array
. Oznacza to, że tworzysz nową kopię tablicy w pamięci.
Praca z references (480MB/220ms)
$array = [];
for ($i=0; $i< 1000000; $i++){
$array[$i] = [
"key" => 'value',
"key2" => $i,
"key3" => $i/3
];
}
foreach ($array as &$item) {
$item['key4'] = 1;
$item['key5'] = 1;
$item['key6'] = 1;
}
z wykorzystaniem &$item
zadajemy PHP dać nam dostęp do zmiennej przez referencję, co oznacza, że mamy do modyfikowania danych bezpośrednio w pamięci bez tworzenia nową kopię tego.
Dlatego właśnie ten skrypt zużywa o wiele mniej pamięci czasu obliczeń.
Praca z klas (223MB/95ms)
Pod maską, PHP używa struktur danych C do zarządzania danymi w pamięci. Klasy są przewidywalne i znacznie łatwiejsze do optymalizacji przez PHP niż tablica. Jest dobrze wyjaśnione here
class TestClass {
public $key1, $key2, $key3, $key4, $key5, $key6;
}
$array = [];
for ($i=0; $i< 1000000; $i++){
$array[$i] = new TestClass();
$array[$i]->key1 = 'value';
$array[$i]->key2 = $i;
$array[$i]->key3 = $i/3;
}
foreach ($array as $item) {
$item->key4 = 1;
$item->key5 = 1;
$item->key6 = 1;
}
Można zobaczyć, że zużycie pamięci & czas do iteracji są znacznie niższe. Wynika to z faktu, że PHP nie musi modyfikować struktury danych w pamięci: każde pole obiektu jest gotowe do odbioru danych.
Należy jednak zachować ostrożność, jeśli doda się pole, które nie zostało zadeklarowane w klasie (np. $item->newKey = 1
: newKey jest zadeklarowane dynamicznie): optymalizacja pamięci nie będzie już możliwa i nastąpi przejście do 620 MB użycia pamięci & 280ms obliczeniowej)
Jeśli chcesz iść dalej i nie boją się bólu głowy, spojrzeć na Standard PHP Library (SPL): znajdziesz wiele zoptymalizowanych rozwiązań struktur danych (stały tablice, Iteratory & więc na ...)
PS: test porównawczy wykonany z Xdebug wyłączony
Protip: zacznij używać obiektów z klasami i wróć do tych z bazą danych, jeśli naprawdę masz tyle danych do pracy, że skończy ci się pamięć. Tak działa pamięć: bufor cpu, jeśli go zabraknie, RAM, jeśli go zabraknie, czas na korzystanie z systemu plików. –
Jeśli masz wystarczająco dużo pamięci, zawsze możesz zwiększyć limit pamięci: - http://php.net/manual/en/ini.core.php#ini.memory-limit – daker
@ Mike'Pomax'Kamermans Dzięki za odpowiedź. Masz na myśli, że powinienem używać wielu obiektów, prawda? – Joe