Jednym z ważniejszych zabiegów optymalizujących kod aplikacji jest używanie przy wykonywaniu poszczególnych operacji, funkcji do tego dedykowanych. Powszechną jest opinia o nadużywaniu np. wyrażeń regularnych, czy też pisaniu własnych funkcji, których odpowiedniki są już zaimplementowane w samym PHP.
Wydobycie rozszerzenia z nazwy pliku nie jest operacją zbyt skomplikowaną i zasobożerną jednak da się ją wykonać na kilka różnych sposobów. Postanowiłem przeprowadzić mały test sprawdzający, które z przyjętych rozwiązań wykona owo zadanie najsprawniej.
Na początek przedstawię kilka sposobów wyekstrahowania rozszerzenia z pełnej ścieżki do pliku.
Na początek użycie funkcji pathinfo
function get_ext_using_pathinfo($path) { $parts = pathinfo($path); return $parts['extension']; }
Użycie funkcji pathinfo ze stałą PATHINFO_EXTENSION – dostępną od wersji PHP 5.2
function get_ext_using_pathinfo_with_const($path) { return pathinfo($path, PATHINFO_EXTENSION); }
Użycie funkcji operujących na tekście substr i strrpos
function get_ext_using_substr_and_strrpos($path) { return substr($path, strrpos($path, ".") + 1); }
Użycie wyrażeń regularnych a dokładnie funkcji preg_replace
function get_ext_using_preg_replace($path) { return preg_replace('/.*\.([a-zA-Z0-9]*)$/', '\\1', $path); }
Użycie wyrażeń regularnych z tymże tym razem funkcji preg_match
function get_ext_using_preg_match($path) { preg_match('/.*\.([a-zA-Z0-9]*)$/', $path, $matches); return $matches[1]; }
Wykonanie exploda i wydobycie ostatniego elementu tablicy funkcją array_pop
function get_ext_using_explode($path) { return array_pop(explode('.', $path)); }
Przez każdą z wyżej wymienionych funkcji – w pętli for – 10 tys. razy przepuściłem zmienną zawierającą przykładową ścieżkę do pliku.
$path = '/home/user/workplace/project/images/file.sufix.ext';
Operację tę wykonałem kilkukrotnie zapisując wyniki do pliku. Po uśrednieniu i zaokrągleniu wyników wyszło mi:
| substr i strrpos | preg_replace | preg_match | pathinfo ze stałą PATHINFO_EXTENSION | explode i array_pop | pathinfo |
|---|---|---|---|---|---|
| 0.077 | 0.0822 | 0.0904 | 0.0952 | 0.1049 | 0.1310 |
Jak wynika z powyższego zestawienia najlepiej spisały się funkcje operujące na stringach. Funkcje preg_replace i preg_match pozytywnie mnie zaskoczyły gdyż spodziewałem się, że zaprzęgnięcie do tak prostej pracy tak potężnej maszyny jaką są wyrażenia regularne będzie obarczone sporą stratą czasu. Z kolei bardzo zawiodłem się na wbudowanej funkcji pathinfo, którą dotąd najczęściej wykorzystywałem do wydobycia potrzebnych mi informacji ze ścieżki. Myślałem, że jest bardziej wydajna, a tu się okazało, że w wersji uniemożliwiającej użycie stałej PATHINFO_EXTENSION jest ona wolniejsza nawet od exploda. Nie skreślałbym tej funkcji w przypadku chęci uzyskania kompletu danych o ścieżce jednak dla atomowej operacji wydobycia rozszerzenia warto pomyśleć o innym sposobie. Z drugiej strony, różnice jak widać nie są znowu tak wielkie, więc dla tego prostego zadania w 99% przypadków użycia nie będzie miało znaczenia, którego z rozwiązań użyjemy i spokojnie możemy kierować się wygodą.


Nowaker
10 sierpnia 2010 at 23:49
Na oko, to Twoje rozwiązanie problemu z substr i strpos poda złą odpowiedź dla „/home/nowaker.net/plik” (poda „net/plik”). Zaś pathinfo, zdaje się, nie pomyli się. Zawsze lepiej używać specjalizowanych metod, niż wymyślać koło na nowo.
Zbigniew Heintze
11 sierpnia 2010 at 14:27
@Nowaker Masz rację, poza tym jak widać różnice w czasach wykonania są niewielkie więc można potraktować ten wpis jako ciekawostkę.