Technologie i narzędzia: język PHP 5, Java, JavaScript, Python, system Zend Framework, Django, biblioteka jQuery, Smarty, platforma Eclipse, MySQL, SVN, CVS, UML, Firefox.
WebProgramming - wszystko o serwisach internetowych
O serwisach internetowych.
[php] Operacje na napisach (string) i ich wydajność (krótka historia)
Od dawna zastanawiałem się, czy operacje na napisach są kosztowne (pamięciowo i/lub obliczeniowo)? W językach typu Java, C# spotykamy specjalną klasą typu StringBuilder, która jest zalecanym sposobem tworzenia napisów (jest optymalną wersją “zwykłych” napisów - optymalną pod względem wykonywania operacji na nich). W przypadku języka PHP takiej klasy nie posiadamy - istnieje tylko prosta zwykła konkatenacja.
Przeprowadzałem proste badanie i okazuje się, iż konkatenacja nie alokuje więcej pamięci niż stworzenie całego napisu ad hoc, wpływa jednak nieznacznie na czas wykonania takiej operacji (jest to związane z niszczeniem i tworzeniem nowego napisu):
-
// Długi napis stworzony ad hoc
-
$str = ‘Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków ….’;
-
// Ten sam napis podzielony na części i "łączony"
-
$str = ‘Długi napis, bardzo długi napis, ‘;
-
$str .= ‘zajmujący kilka tysięcy znaków ….’;
W oby powyższych przypadkach zajętość pamięci jest taka sama, natomiast czas tworzenia napisu różni się o ok 14-17% na korzyść napisu stworzonego w jednym przepisaniu (bez konkatenacji). Nie jest to jednak duża różnica biorąc pod uwagę, iż tworzenie stringa o długości ponad 4 tys znaków zajmuje ok 0.000026 s.
Test był przeprowadzony na dwóch maszynach (laptopie i dzierżawionym serwerze, oba działały pod kontrolą PHP 5.2.6).
Z ciekawostek wartych uwagi jest fakt, iż przypisanie napisu do innej zmiennej nie oznacza alokacji dodatkowej pamięci, jak w tym przypadku:
-
$str = ‘Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków ….’;
-
$tmp = $str;
Pod warunkiem jednak, iż nowo powstały napis nie zostanie zmodyfikowany:
-
$str = ‘Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków ….’;
-
$tmp = $str; // Brak alokacji pamięci dla zmiennej $tmp
-
$tmp .= ”; // Alokowanie pamięci
Innymi słowy niejawnie zmienna jest podstawiona przez “pseudo-referencje” - jeżeli jednak nowo stworzony string się zmieni tworzone jest nowe miejsce w pamięci. Dzieje się tak również w przypadku przekazywania argumentów do funkcji/metody.
Aby zwolnić pamięć zajmowaną przez dany napis wystarczy zrobić jeden z dwóch sposobów:
-
// Pierwszy sposób - czyści zmienną
-
$str = null;
-
// Drugi sposób - bardziej koszerny - likwiduje zmienną
Napisz komentarz