[oop] Eigenschappen instellen met hulpvariabelen
Bar bespaart in snelheid meer dan 22% op Foo. Kan iemand dit snelheidsverschil verklaren?
Code (php)
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
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;
}
}
?>
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;
}
}
?>
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
@Willem, dank je!
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).
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.
Het betekent ook dat je dit in bepaalde situaties dit zou moeten doen:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
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;
}
?>
public function method()
{
$tmp = $this->Property;
// Doe wat dingen met $tmp.
// [...]
$this->Property = $tmp;
}
?>
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... ;-)
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)
maar...
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