== en === benchmark
Ik heb net even zitten te benchmarken.
Ik dacht dat de === (3x) vergelijking altijd sneller zou zijn dan de == (2x) vergelijking. Bij een vergelijking met strings is dit ook het geval. Dan is === (3x) sneller dan == (2x).
Echter, als een functie foo() een boolean teruggeeft dan is
if ($foo)
significant sneller dan
if ($foo === true)
Bij het vergelijken van booleans is == (2x) dus sneller dan === (3x).
Iemand hier een mogelijk verklaring voor? Ik vind het wel bijzonder...
Als je een (echte) boolean met een (echte) boolean wilt vergelijken dan doe je dat altijd met === (3x dus).
Toevoeging op 07/02/2013 13:11:38:
Nu wordt het nog grappiger. Ik denk dat het komt doordat er === achter staat.
Bij if ($test) en if ($test === true) is de 1e variant sneller.
Bij if ($test == true) en if ($test === true) is de 2e variant (verwaarloosbaar) sneller.
Het lijkt dus alsof het stukje "=== true" zorgt voor de vertraging. In if ($test) komt "=== true" niet voor, waardoor blijkbaar de hele vergelijking sneller wordt!
Raar... maar waar, althans zo lijkt het.
Met === vergelijk je op type en value, met == vergelijk je gewoon met value.
Raoul, dat weet ik. Maar is niet het antwoord op mijn vraag! Lees m'n verhaal maar eens door, en vooral de conclusie. Klopt die?
Hetgeen dat tussen de haakjes staat bij if(....) geeft altijd een true of een false waarmee het script verder kan.
Bij if($test) moet de processor alleen $test behandelen en dat levert dan als antwoord een true of false op
En bij if ($test === true) moet het resultaat van $test ook nog eens door de processor vergeleken worden met true.
Technisch dus een extra handeling.
Maar de conclusie zou dan dus zijn dat wanneer je een boolean vergelijkt je het beste dit kunt doen:
if ($testIets())
en wanneer je NIET een boolean vergelijkt je het beste dit kunt doen
if ($testIets() === 'test123') // dus met === (3x)
Dit zijn dan de oplossingen die het gunstigste zijn qua performance. Grappig toch? :)
Hoe pakt je test met if ($foo == true) dan uit? Daar ben ik wel benieuwd naar.
Ozzie PHP op 07/02/2013 13:05:27:
Bij if ($test == true) en if ($test === true) is de 2e variant (verwaarloosbaar) sneller.
Let wel, het verschil is echt verwaarloosbaar hier. Soms was == (2x) zelfs (verwaarloosbaar) sneller.
Maar het verschil tussen if ($test) een if ($test === true) is wel degelijk merkbaar in het voordeel van if ($test). Als je strings gaat vergelijken dan is === (3x) sneller.
Interessant!
Gewijzigd op 07/02/2013 13:36:21 door Ozzie PHP
Ward van der Put op 07/02/2013 13:30:47:
Hoe pakt je test met if ($foo == true) dan uit? Daar ben ik wel benieuwd naar.
if(4 == true) geeft een ander resultaat dan if(4 === true)
Testrapportje:
== Test #1 ==
if (foo()): 8.8563704490662
if (foo() == true): 15.979270935059
if (foo() === true): 12.548780441284
if (true): 4.0895795822144
if (true == true): 4.8216795921326
if (true === true): 4.7458386421204
if ((false === false) === true): 4.991180896759
== Test #2 ==
if (foo()): 8.6794805526733
if (foo() == true): 10.258600711823
if (foo() === true): 9.6942090988159
if (true): 3.7606191635132
if (true == true): 4.8269605636597
if (true === true): 4.7400784492493
if ((false === false) === true): 4.9848699569702
== Test #3 ==
if (foo()): 8.8304209709167
if (foo() == true): 10.144679546356
if (foo() === true): 9.885458946228
if (true): 3.7607502937317
if (true == true): 4.8300004005432
if (true === true): 4.7459292411804
if ((false === false) === true): 4.9861788749695
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
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
<?php
function foo()
{
return true;
}
function DoeTest(){
$aantalHerhalingen = 3000000;
$teller1 = 0;
$teller2 = 0;
$teller3 = 0;
$teller4 = 0;
$teller5 = 0;
$teller6 = 0;
$teller7 = 0;
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo()) {
$teller1++;
}
}
echo 'if (foo()): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo() == true) {
$teller2++;
}
}
echo 'if (foo() == true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo() === true) {
$teller3++;
}
}
echo 'if (foo() === true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true) {
$teller4++;
}
}
echo 'if (true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true == true) {
$teller5++;
}
}
echo 'if (true == true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true === true) {
$teller6++;
}
}
echo 'if (true === true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if ((false === false) === true) {
$teller7++;
}
}
echo 'if ((false === false) === true): ', (microtime(true) - $start) * 10, "<br />\n";
}
$aantalTests = 3;
for ($i = 0; $i < $aantalTests; $i++) {
echo "<br />\n<br />\n== Test #", ($i + 1), " ==<br />\n";
DoeTest();
}
?>
function foo()
{
return true;
}
function DoeTest(){
$aantalHerhalingen = 3000000;
$teller1 = 0;
$teller2 = 0;
$teller3 = 0;
$teller4 = 0;
$teller5 = 0;
$teller6 = 0;
$teller7 = 0;
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo()) {
$teller1++;
}
}
echo 'if (foo()): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo() == true) {
$teller2++;
}
}
echo 'if (foo() == true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (foo() === true) {
$teller3++;
}
}
echo 'if (foo() === true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true) {
$teller4++;
}
}
echo 'if (true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true == true) {
$teller5++;
}
}
echo 'if (true == true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if (true === true) {
$teller6++;
}
}
echo 'if (true === true): ', (microtime(true) - $start) * 10, "<br />\n";
$start = microtime(true);
for ($i = 0; $i < $aantalHerhalingen; $i++) {
if ((false === false) === true) {
$teller7++;
}
}
echo 'if ((false === false) === true): ', (microtime(true) - $start) * 10, "<br />\n";
}
$aantalTests = 3;
for ($i = 0; $i < $aantalTests; $i++) {
echo "<br />\n<br />\n== Test #", ($i + 1), " ==<br />\n";
DoeTest();
}
?>
Ik mis een conclusie Ward :-)
Interessant ik ga even na of ik een aantal dingen (minimaal, dat wel) kan versnellen. Zeker handig voor high traffic websites.
Joeri Bijl op 07/02/2013 15:01:49:
Interessant ik ga even na of ik een aantal dingen (minimaal, dat wel) kan versnellen. Zeker handig voor high traffic websites.
Kijk, is het toch weer ergens nuttig voor :)
Jullie kennen allemaal de wet van Moore? om de 18 maanden wordt een processor dubbel zo krachtig...
Of meer algemeen (doch minder precies): computer-materiaal wordt exponentieel krachtiger, kleiner, goedkoper, meer geheugen.
Er is echter ook een omgekeerde wet van Moore; die uit zich in verschillende aspecten; maar komt er op neer dat men steeds minder de vruchten kan plukken van de toegenomen elektronica.
Vroegere computers gebruikten alles wat ze konden. Programmeurs letten er op dat elke bit goed zou worden gebruikt (een beetje overdrijven om een punt te maken...); ze hielden rekening met de machine waar de software op zou draaien.
(een beetje flauw voorbeeld: ik ken geen enkele pc van vandaag die vlugger kan booten dan mijn oude commodore 64)
Programmeertalen zijn niet geëvolueerd om steeds beter de machine aan te sturen.
Programmeertalen zijn geëvolueerd om steeds beter de programmeur aan te voelen; zodat een programmeur van vandaag op de zelfde tijd veel meer kan realiseren dan gisteren.
Php is op zich een mooi voorbeeld. De losse dataTypes, de OOP principes die niet moeten worden gevolgd (bv. een class waar je je properties kan definiëren met een beginwaarde), geen memory allocation, geen compilering...
Geloof me; dit helpt de snelheid van de computer niet.
Het helpt wel om heel laagdrempelig nieuwe scripters toe te laten in de gemeenschap.
Dus ja ...
Als het om dit soort detail gaat, zou ik zeggen dat de leesbaarheid voor een scripter waarschijnlijk belangrijker is dan de benchmark.
Maar doe vooral verder; laat je niet afleiden door mijn verhaaltjes :)
Gewijzigd op 07/02/2013 15:25:37 door Kris Peeters
Natuurlijk mag je zo denken.
Ik denk omgekeerd. Even uitzoeken wat het snelste werkt en vervolgens dat toepassen. Waarom zou je het immers niet doen? In de praktijk zal ik er nu niet veel van merken. Maar als ik ooit veel sites en veel bezoekers heb dan loont het de moeite dat ik er nu wat moeite in heb gestopt om de juiste keuze te maken ;)
Maar goed, ieder z'n persoonlijke voorkeur natuurlijk!
Maar neem nu bv. pdo, met prepared statements. Dat gebruik je toch niet met de idee dat het de snelheid verhoogt?
Of neem het fetchen van records. Waarom met _assoc() en niet numeriek?
Je kan je voorstellen dat $row['geboortedatum'] trager is dan $row[2].
(moet je misschien eens benchmarken :) )
Waarom? Dat is toch puur voor de leesbaarheid.
Trouwens dito voor elke keer je een string als key gebruikt, voor gelijk wat (soms is het verplicht).
Als je het gevoel hebt: ik kan een paar nanoseconden processor uitsparen; maar als ik dit project over 6 maanden wil verder zetten en hulp nodig heb (bv. op deze site); of wil over laten aan een opvolger; en er is geen kat die begrijpt wat ik daar van plan was...
Dan kan je je vragen stellen over de wenselijkheid van de optimalisatie.
Ik denk in eerste instantie aan dat soort argumenten als ik hier code post.
Zullen ze het begrijpen? Kunnen ze hiermee hulp krijgen op andere forums, ...
De vraag van Ozzie bevat namelijk twee aannamen: foo() is altijd true of false en dus is ook een $foo = foo() altijd true of false. Dat leidt tot complicaties wanneer een verbeterde versie van foo() niet slechts twee maar meer toestanden kent. Om maar te zwijgen van de hark die na $foo = foo() aan de $foo gaat zitten rommelen... Dan laten een if ($foo) en if (!$foo) vervolgens meer toe dan misschien de bedoeling was. Zo introduceer je onbedoelde afhankelijkheden en leg je de voedingsbodem voor bugs en beveiligingslekken.
Toevoeging op 07/02/2013 16:07:08:
@Ward, ik snap niet wat je bedoelt.
Zou jij dan if ($class->hasKey('foo') === true) doen in plaats van if ($class->hasKey('foo'))?
Ozzie PHP op 07/02/2013 16:05:03:
@Ward, ik snap niet wat je bedoelt.
Zou jij dan if ($class->hasKey('foo') === true) doen in plaats van if ($class->hasKey('foo'))?
Zou jij dan if ($class->hasKey('foo') === true) doen in plaats van if ($class->hasKey('foo'))?
Dat hangt ervan af wat er moet gebeuren als aan de conditie is voldaan. Als de code per se uitsluitend op een true mag worden uitgevoerd, zou ik dat inderdaad formaliseren door if ($class->hasKey('foo') === true) te gebruiken. Dat houdt dus alles dat op een true lijkt maar geen true is buiten de deur. Luistert het minder nauw, dan is soms bijvoorbeeld een if ($class->hasKey('foo') != false) meer op zijn plaats.
Dit is sneller en leest (mijns inziens) makkelijker: