Free result & pass by refference vraagje
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class Result{
public $rs;
function foo($var){
return mysql_free_result($var); # memory leak cause of copy of var.
}
function bar(&$var){
return mysql_free_result($var); # no memory leak; pass by refference.
}
function __destruct(){
mysql_free_result($this->rs); # avoid memory leak completely.
}
}
?>
class Result{
public $rs;
function foo($var){
return mysql_free_result($var); # memory leak cause of copy of var.
}
function bar(&$var){
return mysql_free_result($var); # no memory leak; pass by refference.
}
function __destruct(){
mysql_free_result($this->rs); # avoid memory leak completely.
}
}
?>
Dit is correct?
Alvast bedankt,
wat betreft de eerste functie: ja de variabele wordt gekopieerd maar na het verlaten van de functie wordt die kopie ook gelijk weer vrijgegeven. dus is het slechts een zeer kortstondig geheugen verbruik.
Bij de tweede gebeurt bijna hetzelfde zij het dat niet de waarde van een variabele gekopieerd wordt maar het geheugen-adres. ook deze variabele 'verdampt' bij het verlaten van de functie. bij nummer drie zien we in tegenstelling tot de eerste twee een OOP methode. wanneer het geheugen vrij wordt gemaakt wordt eerst de destructor aangeroepen om eventuele 'processen' netjes te beëindigen. Belangrijk is dat je begrijpt dat hier een hele instantie van een class vrijgegeven wordt en niet alleen de variabelen van één functie.
Feitelijk maakt het dus niet zo veel uit welke methode je kiest. Daarbij duurt een gemiddeld php script hooguit enkele seconden waarna ALTIJD al het geheugen van het script weer vrijgegeven wordt, in tegenstelling tot een applicatie die dagen of maanden kan draaien.
Gewijzigd op 29/03/2013 22:49:26 door Frank Nietbelangrijk
Misschien had ik even iets meer sample code moeten geven, want wat je zegt is inderdaad waar voor de eerste twee, mijn excuses.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$foobar = new Result();
$foobar->rs = mysql_query("some very interesting query");
$foobar->foo($foobar->rs); # memory leak, copy of var.
$foobar->bar($foobar->rs); # no memory leak.
# script ended, destructor is called which frees the result of null now.
# But if bar() wasn't called beforehand it would have leaked without this.
?>
$foobar = new Result();
$foobar->rs = mysql_query("some very interesting query");
$foobar->foo($foobar->rs); # memory leak, copy of var.
$foobar->bar($foobar->rs); # no memory leak.
# script ended, destructor is called which frees the result of null now.
# But if bar() wasn't called beforehand it would have leaked without this.
?>
Maar wat ik niet wist, dat alles vrijgegeven word aan het einde van het script zelfs na het niet vrijmaken van het de result; wat is dan het nut aan die functie?
Aangezien een PHP scriptje inderdaad niet lang moet draaien (en als het langer moet, doe je het naar mijn idee niet in de juiste taal) en alles word vrijgegeven dan is dit in principe overbodig in zijn geheel. Theoretisch zou het zelfs ten koste gaan van de render tijd van je pagina.
Of zit ik hier dan foutief te denken?
Gewijzigd op 29/03/2013 23:26:03 door Johan K
nee wat je nu denkt is juist. Ik doe dan ook nooit mysql_free_result() aanroepen. je kunt zelfs op php.net nalezen dat dit automatisch gebeurt. Alleen als je een script schrijft waarin velen malen een nieuw result wordt aangemaakt kun je overwegen of het niet verstandig is om het oude result eerst vrij te geven.
Nu was dit van belang om niet door te kunnen gaan, maar dan weet ik dit voor persoonlijk gebruik.
Dit script is min of meer als een example code voor een sollicitatie, en natuurlijk om het in de resources hier op phphulp te posten want het word naar mijn idee een zeer interessant script.
PDO is fijn om mee te werken, maar ik probeer het compacter te maken.
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$read = new MySQL($host, $user, $pass, $db);
$write = new Postgrsql($host, $user, $pass, $db);
try{
$read->select($what, $table, $read->args(
'user' = $yourusername, // insert $yourusername as is.
'pass' = array('password', $read::post), // will get the value from $POST[] auto escaped.
'somval' = array('myint', $read::post | $read::int) // convert $someval to an integer from post array.
));
# convert query to:
# "select $what from $table where user = '$yourusername', pass = '$password', someval = '0'"
} catch (ConnectionException $e){
die("error connecting to database");
} catch (DatabaseExcveption $e){
die("error in query" . $e->getMessage());
} catch (Exception $e){
die ("unhandled exception");
}
?>
$read = new MySQL($host, $user, $pass, $db);
$write = new Postgrsql($host, $user, $pass, $db);
try{
$read->select($what, $table, $read->args(
'user' = $yourusername, // insert $yourusername as is.
'pass' = array('password', $read::post), // will get the value from $POST[] auto escaped.
'somval' = array('myint', $read::post | $read::int) // convert $someval to an integer from post array.
));
# convert query to:
# "select $what from $table where user = '$yourusername', pass = '$password', someval = '0'"
} catch (ConnectionException $e){
die("error connecting to database");
} catch (DatabaseExcveption $e){
die("error in query" . $e->getMessage());
} catch (Exception $e){
die ("unhandled exception");
}
?>
Dit is even freehand geschreven, kunnen fouten inzitten. '
Elke database type kan geweizigt worden per classe, en kan voor elke database gebruikt worden die ondersteund word in php.
Gewijzigd op 30/03/2013 00:28:22 door Johan K
Frank Nietbelangrijk op 29/03/2013 23:40:05:
nee wat je nu denkt is juist. Ik doe dan ook nooit mysql_free_result() aanroepen. je kunt zelfs op php.net nalezen dat dit automatisch gebeurt. Alleen als je een script schrijft waarin velen malen een nieuw result wordt aangemaakt kun je overwegen of het niet verstandig is om het oude result eerst vrij te geven.
Misschien even toevoegen dat bij mysqli::query() het resultaat uit niet één maar twee resources bestaat als je een query met SELECT uitvoert: een mysqli_result-object in PHP maar ook een bijbehorende resultaatset in MySQL. Het resultaat in PHP is dan geen complete resultaatset, maar meer een handle die aangrijpt op de resultaatset van de databaseserver.
Daarmee heb je naast het object in PHP dus potentieel een tweede geheugenlek: zolang je de resultaatset niet opruimt, blijft deze beschikbaar op de databaseserver. Mede daarom is het toch wel aan te bevelen altijd actief mysqli_result::free() te gebruiken zodra je de resultaatset niet meer nodig hebt.
Gewijzigd op 30/03/2013 09:03:45 door Ward van der Put
net even bekeken op php net. Bij mysqli wordt inderdaad aanbevolen om altijd mysqli_result::free te gebruiken. Bij mysql_free_result niet.
Dit is dan dus een verschil tussen deze twee?
Met andere woorden: er wordt een resultaatset klaargezet op de databaseserver, niet in PHP. Ook bij klassiek mysql in plaats van mysqli zou ik mysql_free_result() gebruiken na een SELECT. Je kunt webserver en databaseserver zien als twee systemen die samenwerken. Na een SELECT staat de resultaatset paraat op de databaseserver, niet de webserver. Een communicatiemechanisme (het PHP-object voor de resultaatset) kopieert daaruit vervolgens data naar je applicatie. Het geheugen dat wordt gebruikt voor het PHP-object bevat geen complete kopie van de resultaatset op de databaseserver.
dank je Ward.