Dziś jest piątek, 12 marca 2010 roku (z kalendarza...)

Struktury danych w SPL-u

Icon

26.07.2008, 19:06

PHP

Komentarze (8)

Powrót

Wertując niedawno dokumentację PHP zabłądziłem do rozdziału poświęconego Standard PHP Library, gdzie moją uwagę przykuły tajemnicze klasy typu SplQueue czy SplMaxHeap. Z ciekawości zajrzałem... yeah! PHP wreszcie otrzyma wbudowane implementacje kilku podstawowych struktur danych! Ujrzymy je najprawdopodobniej w PHP 5.3.

Obecnie programista potrzebujący stosu albo kolejki priorytetowej niestety musi je sobie zaimplementować w samym PHP na bazie zwyczajnej tablicy. O ile proste struktury nietrudno stworzyć za pomocą już istniejących funkcji (np. bierzemy array_unshift() i array_push() i już mamy prostą kolejkę), ale w dalszym ciągu konieczne jest ręczne bawienie się w to. Co więcej, do bardziej zaawansowanych zadań zaczyna szwankować wydajność. Nie dość, że za całość odpowiada kod interpretowany, to jeszcze typ Array pochłania zarówno czas, jak i pamięć na swoje potrzeby (tak naprawdę od strony implementacyjnej jest to tablica z haszowaniem).

Przegląd struktur

Oto lista wszystkich struktur danych, jakie wymienia dokumentacja i/lub zostały zatwierdzone - nie będę dokładnie opisywać, co robi każda ze struktur, ponieważ nie ma za bardzo na to tu miejsca. Jak ktoś wie, to dobrze. Jak nie, a chce zostać zawodowym programistą, powinien nadrobić zaległości.

  1. SplDoublyLinkedList - lista dwukierunkowa
  2. SplStack - stos
  3. SplQueue - kolejka
  4. SplHeap - kopiec
  5. SplMinHeap - kopiec typu min
  6. SplMaxHeap - kopiec typu max
  7. SplPriorityQueue - kolejka priorytetowa
  8. SplFastArray - implementacja szybkich tablic podobnych do tych z C

Szczególnie interesująca jest ostatnia propozycja. Myślę, że wielu programistów korzystało z prostych, kilkuelementowych tablic, których rozmiar znali już na początku. Uniwersalny typ Array to w tym wypadku wyciąganie kombajnu do koszenia trawnika. SplFastArray charakteryzuje się właśnie stałym, predefiniowanym przez nas rozmiarem oraz dopuszczeniem wyłącznie indeksów numerycznych, co przekłada się zarówno na zajętość pamięci, jak i na wydajność. Testy autorów pokazują, że w zależności od platformy, nowy typ jest od 10 do 30% szybszy od Array.

Przykłady

Poniżej parę przykładów wykorzystania pozostałych struktur danych. Załóżmy, że chcemy stworzyć prosty menedżer zadań. Zadania muszą być wykonywane w kolejności określonej przez ich priorytety. Idealnie nadaje się do tego celu kolejka priorytetowa:

<?php
 
$ts = new SplPriorityQueue;
$ts->insert('zadanie 1', 2);
$ts->insert('zadanie 2', 4);
$ts->insert('zadanie 3', 1);
$ts->insert('zadanie 4', 3);
 
foreach($ts as $task)
{
  echo 'Wykonuję '.$task.'<br/>';
}
?>

Skrypt ten wyprodukuje nam:

Wykonuję zadanie 2
Wykonuję zadanie 4
Wykonuję zadanie 1
Wykonuję zadanie 3

Inny przykład to nierekurencyjne przeszukiwanie drzewa:

<?php
 
/* zakladamy, ze mamy strukture drzewka gdzies zaimplementowana */
$tree = generujMiDrzewko();
 
// tworzymy kolejke wezlow oczekujacych na przetworzenie
$queue = new SplQueue;
$queue->enqueue($tree);
 
while($queue->count() != 0)
{
  // pobieramy nastepny w kolejnosci wezel i go przetwarzamy
  $item = $queue->dequeue();
  zrobCosZWezlem($item);
 
  // wsadzamy dzieci tego wezla do kolejki
  foreach($item as $child)
  {
     $queue->enqueue($child);
  }
}
?>

Złożoność

Wiadomo, że w listach dwukierunkowych, stosach i kolejkach dodawanie oraz usuwanie elementów na początku lub końcu będzie wykonywane w czasie jednostkowym (nawet chwalą się tym w dokumentacji). Nic nie wiadomo o implementacji kopców, a tym samym złożoności operacji kolejek priorytetowych. W najgorszym wypadku możemy spodziewać się czasów O(log n) lub O(n), zależnie od operacji. Jeżeli jednak autorzy pokuszą się o kopce Fibonacciego (taką mam nadzieję, w końcu po coś je wymyślono), wtedy prawie wszystkie operacje będą wykonywane w czasie jednostkowym.

Zakończenie

Goście od SPL-a odwalają kawał dobrej roboty. Ech, gdyby tak jeszcze uporządkowano wreszcie API tablic i ciągów tekstowych, byłbym w siódmym niebie... Struktury danych spadają mi dosłownie z nieba, gdyż potrzebuję ich do nowego OPT. Niestety z powodu konieczności czekania na PHP 5.3 na razie napisałem sobie zamienniki w PHP, które ładowane są, jeżeli interpreter nie zawiera właściwych klas. Oby nie kazali czekać zbyt długo.

UPDATE: ukazało się PHP 5.3-alpha1. Zamiast SplFastArray używane jest SplFixedArray.

Powrót

Komentarze

Napisał scanner w niedzielę, 27 lipca 2008 o 01:36

Jak to dobrze, że ktoś coś przeczyta za mnie i się tym podzieli...

Napisał eRIZ w niedzielę, 27 lipca 2008 o 11:56

Wiesz, SPL jest fajny, można go implementować (a powiedziałbym, że nawet trzeba). Tylko w przypadku opisanych przez Ciebie interfejsów, to trzeba by było się głęboko zastanowić - skoro chcesz bazować na nich w OPT, to co w przypadku hostingów? Wiele z nich z naprawdę wielkim bólem nawet pół roku przechodziło z linii 5.1 na 5.2...

Napisał Albi w niedzielę, 27 lipca 2008 o 12:44

No, nareszcie... Wielu takich rzeczy brakuje w PHP... Sądzę, że wszystko idzie w dobrym kierunku. Tylko dlaczegto tak wolno??

Napisał Zyx w poniedziałek, 28 lipca 2008 o 08:04

eRIZ -> ja mam PHP 5.2.6 na komputerze :). Co i jak, masz wyjaśnione przecież w "Zakończeniu".

Napisał eRIZ w poniedziałek, 28 lipca 2008 o 10:57

Zyxie, ja też posiadam najświeższą wersję PHP. Ale po prostu zastanawia mnie to, ile będzie trzeba czekać, aż admini hostingów ruszą swoje cztery litery (a właściwie, to 10 palców ;P) i uaktualnią interpretery, gdy wyjdzie finalna i stabilna wersja...

Napisał Advance w poniedziałek, 28 lipca 2008 o 21:23

No dobrze, ale nie zapominajcie o właścicielach VPS, RPS i dedyków - mają dostawać narzędzia 'II kategorii' wyłącznie przez lenistwo pracowników firm hostingowych? Troszkę myślenie bez sensu i bez perspektyw na przyszłość :)

Napisał WebCM w wtorek, 29 lipca 2008 o 00:40

Rzeczywiście dla niektórych adminów aktualizacja PHP to problem. Pod presją użytkowników są bardziej skłonni, aby to zrobić. Z darmowych serwerów polecam DHost z aktualną wersją PHP i MySQL. :)

Wracając do optymalizacji...
Zdaje się, że instrukcje warunkowe wymagają dużej ilości pamięci. Zaskoczył mnie przypadek: http://www.unit1.pl/pb-841 (PHP 5.2.3). Szczytowe użycie pamięci wynosi 355 KB. Jeśli usunę zarówno blok ELSEIF i ELSE (oznaczyłem miejsce w środkowej części przykładu), spada do 291 KB.

Proste tablice z dozwolonymi tylko numerycznymi indeksami powinny zostać zaimplementowane w jądrze PHP. W SPL raczej będą obiektami.

Napisał Zyx w wtorek, 29 lipca 2008 o 21:06

WebCM -> próby wyciągania wniosków dot. jednej konkretnej instrukcji z rzeczywistego kodu są z góry skazane na niepowodzenie. Skąd wiesz, że to przypadkiem kod zawarty wewnątrz tych bloków nie podbija tego zużycia? Spróbuj zmierzyć to na najprostszym możliwym skrypcie - w każdym bloku proste, identyczne ECHO i nic więcej.

Instrukcje warunkowe z dodatkowymi klauzulami na pewno zajmą trochę więcej pamięci, chociażby z tego powodu, że jest więcej kodu, który jest kompilowany przed uruchomieniem :).

Pamiętaj, dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Skomentuj

NickInformacja
E-mailNa wypadek potrzeby kontaktu z autorem (niepublikowany)
BlogNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2010 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia