[oop] Eigenschappen instellen met hulpvariabelen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ward van der Put
Moderator

Ward van der Put

11/04/2013 08:41:17
Quote Anchor link
In de volgende testopstelling heb ik twee klassen, Foo en Bar, die beide een methode setBody() hebben om de container <body>...</body> van een webpagina vullen. In Foo wordt een eigenschap rechtstreeks met $this->Body ingesteld. In Bar doe ik iets wat ik normaliter liever niet doe: een hulpvariabele $body introduceren en die aan het einde van de rit met $this->Body = $body kopiëren naar de eigenschap.

Bar bespaart in snelheid meer dan 22% op Foo. Kan iemand dit snelheidsverschil verklaren?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
function Test()
{

    $aantal_herhalingen = 100000;
    $timer1 = 0;
    $timer2 = 0;

    $foo = new Foo();
    $start = microtime(true);
    for ($i = 0; $i < $aantal_herhalingen; $i++) {
        $foo->setBody('<p>Lorem ipsum.</p>');
    }

    $timer1 = microtime(true) - $start;

    $bar = new Bar();
    $start = microtime(true);
    for ($i = 0; $i < $aantal_herhalingen; $i++) {
        $bar->setBody('<p>Lorem ipsum.</p>');
    }

    $timer2 = microtime(true) - $start;

    echo 'Foo: ', $timer1, "<br>\n",
         'Bar: ', $timer2, "<br>\n",
         'Verschil: ', 100 * (($timer1 - $timer2) / $timer1), "%<br>\n";
}


$aantal_tests = 5;
for($i = 0; $i < $aantal_tests; $i++){
    echo "<br>\n<br>\n== Test ", ($i + 1), " ==<br>\n";
    Test();
    @
flush();
}



class Foo
{
    private $Body;
    private $Language = 'nl-NL';

    public function setBody($html)
    {

        if (isset($this->Language)) {
            $this->Body = '<body dir="ltr" lang="' . $this->Language . '">';
        }
else {
            $this->Body = '<body dir="ltr">';
        }

        $this->Body .= '<div id="Wrapper">';
        $this->Body .= '<div id="Main">';

        if (is_string($html)) {
            $this->Body .= $html;
        }


        $this->Body .= '<div style="clear:both"></div>';
        $this->Body .= '</div></div>';
        $this->Body .= '</body>';

        return $this;
    }
}



class Bar
{
    private $Body;
    private $Language = 'nl-NL';

    public function setBody($html)
    {

        if (isset($this->Language)) {
            $body = '<body dir="ltr" lang="' . $this->Language . '">';
        }
else {
            $body = '<body dir="ltr">';
        }

        $body .= '<div id="Wrapper">';
        $body .= '<div id="Main">';

        if (is_string($html)) {
            $body .= $html;
        }


        $body .= '<div style="clear:both"></div>';
        $body .= '</div></div>';
        $body .= '</body>';

        $this->Body = $body;
        return $this;
    }
}

?>
 
PHP hulp

PHP hulp

19/04/2024 17:19:28
 
Willem vp

Willem vp

11/04/2013 09:46:18
Quote Anchor link
Quote:
Bar bespaart in snelheid meer dan 22% op Foo. Kan iemand dit snelheidsverschil verklaren?

Heel simpel: dereferencen in PHP is traag.

Als je een property meer dan twee keer nodig hebt, is het sneller om een lokale variabele te gebruiken, zodat je maar maximaal 2 dereferences hebt (een voor het ophalen en een voor het setten van de waarde).
Gewijzigd op 11/04/2013 10:08:42 door Willem vp
 
Ward van der Put
Moderator

Ward van der Put

11/04/2013 09:51:11
Quote Anchor link
@Willem, dank je!
 
Ozzie PHP

Ozzie PHP

11/04/2013 14:03:18
Quote Anchor link
Willem vp op 11/04/2013 09:46:18:
Heel simpel: dereferencen in PHP is traag.

Als je een property meer dan twee keer nodig hebt, is het sneller om een lokale variabele te gebruiken, zodat je maar maximaal 2 dereferences hebt (een voor het ophalen en een voor het setten van de waarde).

Hé, had ik dat zelf ook laatst al niet ondervonden Ward ;) Dat ik zei dat als je een class property in een functie meer dan 1x gebruikt je beter een lokale kopie kunt gebruiken... en oh oh, wat kreeg ik een reacties over me heen :) Check het topic.
 
Ward van der Put
Moderator

Ward van der Put

11/04/2013 14:21:11
Quote Anchor link
Het snelheidsverschil is significant en groot, van minder dan 120 naar 150 km per uur :)

Het betekent ook dat je dit in bepaalde situaties dit zou moeten doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
public function method()
{

    $tmp = $this->Property;

    // Doe wat dingen met $tmp.
    // [...]


    $this->Property = $tmp;
}

?>
 
Willem vp

Willem vp

11/04/2013 14:28:43
Quote Anchor link
Ward van der Put op 11/04/2013 14:21:11:
Het snelheidsverschil is significant en groot, van minder dan 120 naar 150 km per uur :)

Ach, je mag toch nergens 150 rijden... ;-)
 
Ozzie PHP

Ozzie PHP

11/04/2013 14:34:54
Quote Anchor link
@Ward, dat is dus ook precies hoe ik het doe... en waar ik de vorige keer een hoop commentaar op kreeg (zie topic). Zo zie je maar weer... soms is het goed om even verder te kijken dan de neus lang is.

Ook als je de property niet set, maar er uitsluitend gegevens uithaalt (en dat meerdere keren) kun je beter een lokale kopie maken.

Dus niet:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php

public function foo() {
  $foo = array();
  $foo['foo']    = $this->data['foo'];
  $foo['bar']    = $this->data['bar'];
  $foo['foobar'] = $this->data['foobar'];
}


?>

maar...

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php

public function foo() {
  $foo  = array();
  $data = $this->data;
  $foo['foo']    = $data['foo'];
  $foo['bar']    = $data['bar'];
  $foo['foobar'] = $data['foobar'];
}


?>
 
Willem vp

Willem vp

11/04/2013 14:55:19
Quote Anchor link
Quote:
Bar bespaart in snelheid meer dan 22% op Foo.

Op mijn server (en dat is een doos uit 2006, dus niet een van de snelste meer) is Bar gemiddeld slechts zo'n 6% sneller.

En dan hebben we het dus over 0,35 seconden i.p.v. 0,37. Maar liefst 2/100 seconde snelheidswinst op 100000 iteraties. Dat noemen we nou micro-optimalisaties. ;-)

Zoals ik in het hierboven aangehaalde oudere Ozzie-topic ook al zei: om te bepalen of je een tijdelijke variabele moet gebruiken, is leesbaarheid wellicht een beter criterium dan snelheid.

Toevoeging op 11/04/2013 15:04:35:

Overigens zou je voor een betere benchmark je loop in de setBody-method moeten uitvoeren. Nu meet je namelijk ook de overhead van het aanroepen van je method mee.

Op mijn server scheelt dat zo'n 0,1 seconde per testrun. De verschillen blijven absoluut gezien even groot (zo'n 0,02 sec) waardoor de snelheidswinst van Bar marginaal stijgt naar gemiddeld 10%.
Gewijzigd op 11/04/2013 15:04:58 door Willem vp
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.