Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Singleton] Wydajność
Forum PHP.pl > Forum > PHP > Object-oriented programming
Astarot
Witam, postanowiłem przetestować czas wykonywania skryptu dla klasy skonstruowanej wg. wzorca Singleton, wywoływanej poprzez metode statyczną która decyduje czy należy tworzyć nowy obiekt klasy. Wywoływałem tą klasę również w tradycyjny sposób. Czas wykonywania skryptu wyglądał
następująco :

Kod
Skrypt wykonany w czasie: 1.485986 sekundy (tradycyjnie wywołany obiekt)
Skrypt wykonany w czasie: 2.203427 sekundy(wg. singleton)


Byc moze zle implementuje ten wzorzec w swojej aplikacji wiec podaje poniżej kod :

  1. <?php
  2.  
  3. class Test2
  4. {
  5. public $licznik;
  6.  
  7. private static $oInstance = false;
  8.  
  9.  
  10. public static function getinstance ( )
  11. {
  12. if ( self::$oInstance == false )
  13. {
  14. self::$oInstance = new Test2( );
  15. }
  16. return self::$oInstance;
  17. }
  18. public function mnozenie()
  19. {
  20. return $this->licznik*10;
  21. }
  22. } 
  23.  
  24. ?>


Klasę wywołuję wg singleton tym kodem:

  1. <?php
  2.  
  3. for($i=0; $i<80000; $i++)
  4. {
  5. $test =& Test2::getinstance ( ); 
  6. $test->licznik=$test->licznik++;
  7. echo $test->mnozenie();
  8. }
  9.  
  10. ?>


A tak tworze obiekt klasy w tradycyjny sposób(wg. moich testów ten sposób jest szybszy)
  1. <?php
  2.  
  3. for($i=0; $i<80000; $i++)
  4. {
  5. $test = New Test2( ); 
  6. $test->licznik=$test->licznik++;
  7. echo $test->mnozenie();
  8. }
  9.  
  10. ?>


Czy może mi ktoś wyjaśnić dlaczego kod wg singleton jest wykonywany wolniej i kiedy warto
w swoich aplikacjach implementować ten wzorzec ?

Z góry dzieki za pomoc.
hwao
Roznica jest nie wielka.

Singleton jak sama nazwa wskazuje jest uzywany tam gdzie w calej aplikacji musi byc tylko jedna wersja obiektu i tego trzeba sie trzymac.
LBO
Dodam tylko, że funkcjonalność tego wzorca jest na tyle duża, że pomija się raczej takie małe wady. O ile tę małą różnicę można nazwać wadą, bo wyobraź sobie jakie narzuty na czas wykonywania, miałoby przekazywanie obiektów przez parametr/referencję - bo właśnie temu singleton zapobiega.
mariuszn3
Hmm.. a spróbuj taką wersję (przynajmniej to co napisałeś trochę mi nie pasuje):
Singleton:
  1. <?php
  2.  
  3. class TestSingleton {
  4. private $licznik = 0;
  5. private static $oInstance = false;
  6.  
  7. public static function set_instance() {
  8. if (self::$oInstance === false) {
  9. self::$oInstance = new Test2();
  10. ++self::$oInstance->licznik;
  11. }
  12. }
  13.  
  14. public static function mnozenie() {
  15. return self::$oInstance->licznik*10;
  16. }
  17. }
  18. for($i=0; $i<80000; ++$i) {
  19. TestSingleton::set_instance();
  20. echo TestSingleton::mnozenie();
  21. }
  22.  
  23. ?>


Tradycyjny sposób:
  1. <?php
  2.  
  3. class Test {
  4. private $licznik = 0 ;
  5.  
  6. public function __construct() {
  7. ++$this->licznik;
  8. }
  9.  
  10. public function mnozenie() {
  11. return $this->licznik*10;
  12. }
  13. }
  14.  
  15. for($i=0; $i<80000; ++$i) {
  16. $test = new Test;
  17. echo $test->mnozenie();
  18. }
  19.  
  20. ?>


Nie mówię, że będzie dużo lepiej, ale kod jakby właściwszy mi się wydaje.
Hacker
Cytat(Astarot @ 2006-05-03 07:18:34)
Klasę wywołuję wg singleton tym kodem:

  1. <?php
  2.  
  3. for($i=0; $i<80000; $i++)
  4. {
  5. $test =& Test2::getinstance ( ); 
  6. $test->licznik=$test->licznik++;
  7. echo $test->mnozenie();
  8. }
  9.  
  10. ?>


A tak tworze obiekt klasy w tradycyjny sposób(wg. moich testów ten sposób jest szybszy)
  1. <?php
  2.  
  3. for($i=0; $i<80000; $i++)
  4. {
  5. $test = New Test2( ); 
  6. $test->licznik=$test->licznik++;
  7. echo $test->mnozenie();
  8. }
  9.  
  10. ?>

zły test, chociaż wyniki poprawne singleton jest trochę wolniejszy.
  1. <?php
  2. $test->licznik=$test->licznik++;
  3. ?>
nigdy nie zwiększy $test->licznik
$zmienna++ zwiększa wartość zmiennej PO użyciu, a nie PRZED
mój kod testujący
  1. <?php
  2. class Test2
  3. {
  4.  
  5. public $licznik = 1;
  6.  
  7. public static function getinstance()
  8. {
  9. static $instance;
  10. if (!isset($instance))
  11. $instance = new Test2();
  12. return $instance;
  13. }
  14. public function mnozenie()
  15. {
  16. return $this->licznik*10;
  17. }
  18. } 
  19.  
  20. class Test
  21. {
  22. public $licznik = 1;
  23.  
  24. public function mnozenie()
  25. {
  26. return $this->licznik*10;
  27. }
  28. }
  29. function getmicrotime()
  30. {
  31. list($usec, $sec) = explode(" ", microtime());
  32. return ((float)$usec + (float)$sec);
  33. }
  34. $temp = 0;
  35. $time_start = getmicrotime();
  36. for($i=0; $i<1000000; $i++)
  37. {
  38. $test = Test2::getinstance();
  39. $test->licznik=++$temp;
  40. $temp = $test->licznik;
  41. $test->mnozenie();
  42. }
  43. $time_end = getmicrotime();
  44. echo 'Singleton: '.($time_end-$time_start).'s <br>';
  45.  
  46. $temp = 0;
  47. $time_start1 = getmicrotime();
  48. for($i=0; $i<1000000; $i++)
  49. {
  50. $test = New Test( ); 
  51. $test->licznik=++$temp;
  52. $temp = $test->licznik;
  53. $test->mnozenie();
  54. }
  55. $time_end1 = getmicrotime();
  56. echo 'Normal: '.($time_end1-$time_start1).'s';
  57. ?>

a wyniki
Kod
Singleton: 8.5278367996216s
Normal: 6.6726980209351s

Takie wyniki uzystałem na moim AMD Athlon 2500+ (Barton)

-edit-
2 min później lol
em1X
Przeciez w singletonie nie chodzi o wydajnosc, ale o to, zeby klasa nie mogla byc powielana wieloma obiektami!

Przypominam, ze powinien byc jeszcze zdefiniowany prywatny konstruktor (w twoim przypadku go nie ma i mozna tworzyc obiekty tej klasy)
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.