Dostęp do dużych tablic w PHP
Robiłem profilowanie różnych metod uzyskiwania dostępu do dużych (ish) tablic danych w PHP. Przypadek użycia jest całkiem prosty: niektóre z naszych narzędzi przesyłają dane do plików PHP jako tablice asocjacyjne, a te pliki są uważane przez aplikację za dane statyczne. Tworzymy gry, więc niektóre przykłady plików danych obejmują elementy w katalogu, zadania, które użytkownik musi wykonać, lub definicje map:
<code><?php $some_data = array( ...lots and lots of stuff in here... ); ?> </code>
Ponieważ te macierze są duże (400K), a większość naszego kodu jest zainteresowana tymi danymi, konieczne staje się uzyskanie dostępu do tych danych tak efektywnie, jak to możliwe. Postanowiłem wykonać 3 różne wzorce. Po przedstawieniu metod przedstawię poniżej moje wyniki.
To, czego szukam, to pewna walidacja oparta na doświadczeniu w zakresie tych metod i ich czasu, a także wszelkich innych metod wypróbowania.
Metoda # 1: funkcja getteraW metodzie eksporter faktycznie tworzy plik, który wygląda jak:
<code><?php function getSomeData() { $some_data = array( ...lots and lots of stuff here... ); return $some_data; } ?> </code>
Kod klienta może następnie pobrać dane, po prostu wywołując metodę getSomeData (), gdy tego chcą.
Metoda # 2: global + includeW tej metodzie plik danych wygląda identycznie jak oryginalny blok kodu powyżej, jednak kod klienta musi przeskoczyć kilka obręczy, aby uzyskać dane w lokalnym zasięgu. Zakłada to, że tablica znajduje się w pliku o nazwie „some_data.php”;
<code>global $some_data; //must be the same name as the variable in the data file... include 'some_data.php'; </code>
Spowoduje to przeniesienie tablicy $ some_data do zakresu, choć jest to trochę kłopotliwe dla kodu klienta (moja opinia).
Metoda # 3: getter przez odniesienieTa metoda jest prawie identyczna z metodą nr 1, jednak funkcja getter nie zwraca wartości, ale raczej ustawia odniesienie do danych.
<code><?php function getSomeDataByRef($some_data) { $some_data = array( ...lots and lots of stuff here... ); return $some_data; } ?> </code>
Następnie kod klienta pobiera dane, deklarując zmienną lokalną (nazywaną dowolną) i przekazując ją przez odniesienie do gettera:
<code>$some_data_anyname = array(); getSomeDataByRef(&$some_data_anyname); </code>Wyniki
Uruchomiłem więc mały skrypt, który uruchamia każdą z tych metod pobierania danych 1000 razy i uśrednia czas pracy (obliczany przez mikrotim (prawda) na początku i na końcu). Oto moje wyniki (w ms, uruchomione na MacBookPro 2 GHz, 8 GB RAM, wersja PHP 5.3.4):
METODA 1:AVG: 0,0031637034416199 MAX: 0,0043289661407471 MIN: 0,0025908946990967
METODA 2:AVG: 0.01434082698822 MAX: 0.018275022506714 MIN: 0.012722969055176
METODA 3:AVG: 0,00335768699646 MAX: 0,0043489933013916 MIN: 0,0029017925262451
Mimo to wydaje się całkiem jasne, że metoda global + include jest gorsza od pozostałych dwóch, które są „pomijalną” różnicą.
Myśli? Czy czegoś mi kompletnie brakuje? (prawdopodobnie...)
Z góry dziękuję!