Parameter-Übergabe mittels pass-by-reference
Post removed (X-No-Archive: yes)
Re: Parameter-Übergabe mittels pass-by-reference
Karl Huber schrieb:
> Da das Array zehntausende Elemente enthält, und in der Vergangenheit =
> einige PHP-Versionen ernsthafte Performanceprobleme mit der
> Array-Verarbeitung hatten, übergebe ich das Array an die Funktion
> array_reverse() als Referenz.
Das wäre übel, weil sich das Array während der Verarbeitung durch d=
ie
Funktion verändern würde - mit unvorhersagbaren Ergebnissen.
Die =DCbergabe als Referenz hätte auch keinen Einfluss auf die Performa=
nz,
sondern nur auf den Speicherverbrauch.
> Macht es überhaupt Sinn, in so einem Fall einen Parameter an eine
> PHP-interne Funktion als Referenz zu übergeben?
Nein.
> Oder ist der
> PHP-Interpreter in so einem Fall sowieso so intelligent, dass beim
> Funktionsaufruf keine Kopie des Arrays erzeugt wird?
Möglich, aber IMHO nicht wahrscheinlich.
Wenn du Speicher sparen musst, könnte folgender Ansatz helfen (ungetest=
et):
$newArray =3D array();
while ( !empty( $oldArray ) ) {
end( $oldArray );
$newArray[key( $oldArray )] =3D array_pop( $oldArray );
};
Das alte Array wird laufend verkürzt, während das neue aufgebaut wird=
=2E
MfG
Niels
--
| http://www.kolleg.de =B7 Das Portal der Kollegs in Deutschland |
| http://www.bsds.de =B7 BSDS Braczek Software- und DatenSysteme |
| Webdesign =B7 Webhosting =B7 e-Commerce =B7 Joomla! Content Management =
|
------------------------------------------------------------ ------
Re: Parameter-Übergabe mittels pass-by-reference
Niels Braczek wrote:
> Das wäre übel, weil sich das Array während der Verarbeitung durch die
> Funktion verändern würde - mit unvorhersagbaren Ergebnissen.
Das ist doch immer so bei Funktionen, die einen per Referenz übergebenen
Parameter verändern. Es dürfte doch auch nicht stören, solange man nicht
irgendwie per Multithreading oder so noch zusätzlich auf die Variable
zugreift. Aber geht das in PHP überhaupt?
Ich hab die verschiedenen Möglichkeiten mal ausprobiert:
---8<---
$oldArray = array(1, 2, 3);
array_reverse(&$oldArray);
print_r($oldArray);
print_r(array_reverse($oldArray));
$newArray = array();
while ( !empty( $oldArray ) ) {
end( $oldArray );
$newArray[key( $oldArray )] = array_pop( $oldArray );
}
print_r($newArray);
---8<---
ergibt:
---8<---
Warning: Call-time pass-by-reference has been deprecated; If you would
like to pass it by reference, modify the declaration of array_reverse().
If you would like to enable call-time pass-by-reference, you can set
allow_call_time_pass_reference to true in your INI file in
/home/magnum/test/array.php on line 7
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 3
[1] => 2
[2] => 1
)
Array
(
[2] => 3
[1] => 2
[0] => 1
)
---8<---
Die Übergabe per Referenz funktioniert also gar nicht, das Array wird
nicht verändert. Die Funktion von Niels unterscheidet sich von
array_reverse() dadurch, dass die Indizes beibehalten werden.
Ich habe dann noch einen Performancevergleich gemacht:
---8<---
$oldArray = array();
for ($i=0; $i<100000; $i++) {
$oldArray[] = md5(rand(1, 10000));
}
$refArray = array_reverse($oldArray);
function a1($oldArray) {
$newArray2 = array_reverse($oldArray);
}
function a2($oldArray) {
$newArray = array();
while ( !empty( $oldArray ) ) {
end( $oldArray );
$newArray[key( $oldArray )] = array_pop( $oldArray );
}
}
$functions = array(1, 2);
$times = array(1=>0, 2=>0);
for ($i=1; $i<=5; $i++) {
shuffle($functions);
foreach ($functions as $f) {
$starttime = microtime(true);
call_user_func('a'.$f, $oldArray);
$times[$f] += microtime(true) - $starttime;
}
}
print_r($times);
---8<---
ergibt:
---8<---
Array
(
[1] => 0.888491153717
[2] => 53.1437022686
)
---8<---
Der möglichen Speicherersparnis steht also eine längere Rechenzeit
gegenüber. Naja, nicht wirklich verwunderlich.
cu, Magnus
--
Carl Magnus Rosenbaum M.A.
Administration - Programmierung - Weiterbildung http://cmr.cx/
Tel: +49 89 70066626 Fax: +49 89 70066686 Mobil: +49 163 7006662
PGP Fingerprint: DEBC 3C99 EF1D 74F0 D4C7 EFF5 C268 3690 0EA1 7641
Re: Parameter-Übergabe mittels pass-by-reference
Magnus Rosenbaum schrieb:
> Das ist doch immer so bei Funktionen, die einen per Referenz übergebenen
> Parameter verändern. Es dürfte doch auch nicht stören, solange man nicht
> irgendwie per Multithreading oder so noch zusätzlich auf die Variable
> zugreift. Aber geht das in PHP überhaupt?
Multithreading geht doch soweit ich weiß an der Stelle eigentlich nicht,
weil jeder Seitenaufruf sein eigener Speicherbereich besitzt, also ein
eigener Prozess ist.
Besteht überhaupt die relevant gerade hier zu optimieren? Ist diese
Stelle der Engpass bei deinen Performanceproblemen?
Ich gehe davon aus, dass die PHP Methode schneller ist, da in C
geschrieben, als das was in PHP selbst an Methoden schreiben kannst. Von
daher ist die Frage ob in PHP überhaupt etwas bewirken kannst oder nicht
bei einer n C geschriebenen Variante anfangen musst.
> Warning: Call-time pass-by-reference has been deprecated; If you would
> like to pass it by reference, modify the declaration of array_reverse().
> If you would like to enable call-time pass-by-reference, you can set
> allow_call_time_pass_reference to true in your INI file in
> /home/magnum/test/array.php on line 7
Ich brauche dies selten, aber muss nicht die Methode die Referenz
annehmen statt der Parameter eine Referenz bieten?
Also nicht:
function bla($var) { ... }
bla(&$var);
Sondern:
function bla(&$var) { ... }
bla($var);
Von daher dürfte es recht schwer werden, an dem Zustand etwas zu ändern
ohne tiefer einzugreifen.
--
Mit freundlichen Grüßen,
Christoph Herrmann
http://dragonprojects.de/
Re: Parameter-Übergabe mittels pass-by-reference
Christoph Herrmann wrote:
> Ich brauche dies selten, aber muss nicht die Methode die Referenz
> annehmen statt der Parameter eine Referenz bieten?
Zumindest in früheren PHP-Versionen ging beides. In aktuellen Versionen
wird eine (abschaltbare) Warnung ausgegeben, sollte aber noch
funktionieren. In Zukunft wird es irgendwann nicht mehr möglich sein:
"wird möglicherweise in späteren Version von PHP/Zend nicht mehr unterstützt".
> Von daher dürfte es recht schwer werden, an dem Zustand etwas zu ändern
> ohne tiefer einzugreifen.
Gibt's sowas wie "Inline C" bei Perl eigentlich auch für PHP?
--
Carl Magnus Rosenbaum M.A.
Administration - Programmierung - Weiterbildung http://cmr.cx/
Tel: +49 89 70066626 Fax: +49 89 70066686 Mobil: +49 163 7006662
PGP Fingerprint: DEBC 3C99 EF1D 74F0 D4C7 EFF5 C268 3690 0EA1 7641
Re: Parameter-Übergabe mittels pass-by-reference
Post removed (X-No-Archive: yes)
Re: Parameter-Übergabe mittels pass-by-reference
Magnus Rosenbaum schrieb:
> Gibt's sowas wie "Inline C" bei Perl eigentlich auch für PHP?
http://pear.php.net/package/Inline_C
MfG
Niels
--
| http://www.kolleg.de =B7 Das Portal der Kollegs in Deutschland |
| http://www.bsds.de =B7 BSDS Braczek Software- und DatenSysteme |
| Webdesign =B7 Webhosting =B7 e-Commerce =B7 Joomla! Content Management =
|
------------------------------------------------------------ ------
Re: Parameter-Übergabe mittels pass-by-reference
Post removed (X-No-Archive: yes)
Re: Parameter-Übergabe mittels pass-by-reference
Karl Huber schrieb:
> Niels Braczek schrieb:
>
>> http://pear.php.net/package/Inline_C
>
> Könnte man theoretisch in so einer Inline-C-Funktion Inline-Assembler=
> schreiben?
Ich weiß nicht, wie das implementiert ist, denke aber: eher nicht.
> Wenn ja, wäre es ja wirklich eine zumindest theoretische Möglichkei=
t für
> sehr einfache, aber oftmalige/rechenintensive Operationen ...
Dann schreibst du einfach eine Extension für PHP. Das ist sicher wenige=
r
problematisch als Inline C, das offenbar seit =C4onen nicht gepflegt wird=
wird und es nicht mal zu 1 Seite Dokumentation gebracht hat.
MfG
Niels
--
| http://www.kolleg.de =B7 Das Portal der Kollegs in Deutschland |
| http://www.bsds.de =B7 BSDS Braczek Software- und DatenSysteme |
| Webdesign =B7 Webhosting =B7 e-Commerce =B7 Joomla! Content Management =
|
------------------------------------------------------------ ------
Re: Parameter-Übergabe mittels pass-by-reference
Karl Huber wrote:
> Greift ihr auf die einzelnen Array-Elemente mittels Referenz zu, oder
> lässt ihr von der foreach-Schleife jeweils eine Kopie von jedem Element
> erstellen, so wie es bei normalem Gebrauch üblich ist?
Wie kann man denn verhindern, dass foreach die Kopien erstellt?
--
Carl Magnus Rosenbaum M.A.
Administration - Programmierung - Weiterbildung http://cmr.cx/
Tel: +49 89 70066626 Fax: +49 89 70066686 Mobil: +49 163 7006662
PGP Fingerprint: DEBC 3C99 EF1D 74F0 D4C7 EFF5 C268 3690 0EA1 7641
Re: Parameter-Übergabe mittels pass-by-reference
Post removed (X-No-Archive: yes)
Re: Parameter-Übergabe mittels pass-by-reference
Karl Huber wrote:
> foreach ($array as &$arrayElement) {
Wieder was gelernt.
Ich habe in den User Contributed Notes zu foreach aber gesehen, dass ein
neues Setzen von $arrayElement nach der foreach-Schleife logischerweise
auf das letzte Element von $array zugreift. Das ist schon eine ziemlich
üble Falle.
Also würde ich das nur bei sehr großen Arrays hernehmen und dann nach der
Schleife unbedingt ein unset($arrayElement) machen.
cu, Magnus
--
Carl Magnus Rosenbaum M.A.
Administration - Programmierung - Weiterbildung http://cmr.cx/
Tel: +49 89 70066626 Fax: +49 89 70066686 Mobil: +49 163 7006662
PGP Fingerprint: DEBC 3C99 EF1D 74F0 D4C7 EFF5 C268 3690 0EA1 7641
Re: Parameter-Übergabe mittels pass-by-reference
..oO(Magnus Rosenbaum)
>Karl Huber wrote:
>> foreach ($array as &$arrayElement) {
>
>Wieder was gelernt.
>
>Ich habe in den User Contributed Notes zu foreach aber gesehen, dass ein
>neues Setzen von $arrayElement nach der foreach-Schleife logischerweise
>auf das letzte Element von $array zugreift. Das ist schon eine ziemlich
>üble Falle.
Durchaus. Man muß halt aufpassen, was man mit der "Laufvariablen" vor
und auch nach der Schleife macht. Siehe dazu auch den Thread
<news:1182859313.904235.135860 [at] p77g2000hsh.googlegroups.com> und
insbesondere <news:468251CB.60809 [at] gmx.de> für eine Erklärung.
>Also würde ich das nur bei sehr großen Arrays hernehmen und dann nach der
>Schleife unbedingt ein unset($arrayElement) machen.
Kommt drauf an.[tm] Wenn man sich der möglichen Konsequenzen bewußt ist,
dann ist das eine durchaus elegante Möglichkeit, innerhalb der Schleife
direkt auf die Array-Elemente zugreifen zu können ohne den "Umweg" über
foreach ($array as $key => $value) {
$array[$key] = ...
}
Micha