Frage zu Singelton
Bene
- php
-1 Jeena Paradies0 Tom0 Bene0 Sven Rautenberg
Hallo,
ich habe in einer Config Datei alle Texte die ich auf der Website einsezten will, wie kurze Erläuterungen, etc. Da die Texte von anderen gepflegt werden müssen, muss ich sie auslagern. Ich greife dann mit der Funktion parse_ini_file darauf zu.
Damit die Dateien nich jedes mal neu eingelesen werden müssen, will ich dies nur einmal tun und habe gedacht, dass ich das mit einem Singleton umsetzen kann. Mein Gedanke war: nur beim ersten mal die Dateien in ein Array einlesen und bei jedem weiteren Zugriff auf dieses Array zugreifen.
Ist dies überhaupt so umsetzbar? Ich habe nämlich das Beispiel aus dem Manual kopiert und im Konstruktor eine echo Ausgabe erzeugt. Das Ergebnis: bei jedem Aktualisieren der Seite wird der Konstruktor aufgerufen, was ja nicht in meinem Sinne ist...
Geht das überhaupt nicht so wie ich es mir vorstelle?
Danke für die Hilfe
Bene
Hallo,
Christian Kruse hat mir mal diese Funktion genau für so einen Fall geschrieben:
function my_serialize_cfg($arg) {
if(is_string($arg)) return "'".preg_replace("/'/","\\'",$arg)."'";
elseif(is_integer($arg)) return (string)$arg;
elseif(is_float($arg)) return (string)$arg;
elseif(is_null($arg)) return 'NULL';
elseif(is_bool($arg)) {
if($arg) return 'true';
else return 'false';
}
elseif(is_array($arg)) {
$retval = 'Array(';
foreach($arg as $key => $value) {
$retval .= my_serialize_cfg($key).' => '.my_serialize_cfg($value).',';
}
$retval .= ')';
return $retval;
}
else die("unsupported type! ".gettype($arg));
}
Damit bekommt man alles was man da eingibt als string zurück. Wenn du da also so ein Array ($myarray) hast und es damit behandelst dann kannst du ungefähr so dieses Array in eine Datei schreiben (um es dann einfach mit [link:http://php.net/require_once@title=require_once]('myarray.php');
zu includen):
[link:http://php.net/file_put_contents@title=file_put_contents]('myarray.php', my_serialize_cfg($myarray));
Grüße
Jeena Paradies
echo $begrüßung;
Christian Kruse hat mir mal diese Funktion genau für so einen Fall geschrieben:
Was war der Grund, dass er dir das mal geschrieben hat, wo es doch serialize()/unserialize() oder auch var_export() gibt?
echo "$verabschiedung $name";
Hallo,
Was war der Grund, dass er dir das mal geschrieben hat, wo es doch serialize()/unserialize() oder auch var_export() gibt?
Ähm serialize()/unserialize() sind da doch ziemlich aufwendig, da man diese Daten bei jedem aufruf irgendeiner Seite braucht spaart man sich da schon mal einiges dadurch dass es gleich als Array abgespeichert ist. Ich habe aber natürlich nicht gemessen.
Hm ok und warum ich nicht var_export() benutzte? Weil weder ich noch er wussten dass es so etwas gibt ;-). Naja das war ja auch ne gute Übung, denn mittlerweile könnte ich so etwas auch alleine schreiben.
Grüße
Jeena Paradies
Moin,
Ähm serialize()/unserialize() sind da doch ziemlich aufwendig, da man diese Daten bei jedem aufruf irgendeiner Seite braucht spaart man sich da schon mal einiges dadurch dass es gleich als Array abgespeichert ist.
Eigentlich ist es umgekehrt: serialize/unserialize machen die Signalisierung out-of-band und sind deshalb weniger aufwendig. In PHP-Syntax geht ein String vom ' bis zum nächsten ', ausser wenn da ein \ vor steht, es sei denn davor ist ein \ usw. Da muss richtig geparsed werden, und das ist komplex. In der serialize-Syntax steht am Anfang sowohl der Typ (den PHP sonst nur implizit erkennen kann) als auch die Länge, unserialize muss also nur noch x Bytes lesen, ohne sie sich anzuschauen.
Ich habe aber natürlich nicht gemessen.
Ich habe das grade mal getan und es bestätigt meine Intuition (auch wenn der Unterschied schwächer ausfällt, als vermutet):
save.php:
<?php
$a = Array();
for($i=0; $i < 1000; $i++) {
$b = "";
for($j=0; $j < 100; $j++) {
$b .= chr(rand(0,255));
}
$a[] = $b;
}
$c = var_export($a, true);
$d = serialize($a);
$fh = fopen("var_exported", "wb");
fwrite($fh, "<?php \$a=" . $c . ";");
fclose($fh);
$fh = fopen("serialized", "wb");
fwrite($fh, $d);
fclose($fh);
?>
load-serialize.php:
<?php
$a = unserialize(file_get_contents("serialized"));
echo count($a);
?>
load-var_export.php:
<?php
include("var_exported");
echo count($a);
?>
Zeit für 1000 mal load-serialize: 13m48.256s
Zeit für 1000 mal load-var_export: 14m23.399s
(Geschätzte Genauigkeit liegt in der Gegend von 10 Sekunden)
Hmm, das sind nur ca. 4%, ich hätte mehr erwartet. Vermutlich geht der Löwenanteil der Arbeit für das Laden des PHP-Interpreters drauf, und wenn man den Stunt mehrfach in einem Skript (mit verschiedenen Datensätzen versteht sich) durchzieht wird der Unterschied größer.
Hallo,
Eigentlich ist es umgekehrt: serialize/unserialize machen die Signalisierung out-of-band und sind deshalb weniger aufwendig. In PHP-Syntax geht ein String vom ' bis zum nächsten ', ausser wenn da ein \ vor steht, es sei denn davor ist ein \ usw. Da muss richtig geparsed werden, und das ist komplex. In der serialize-Syntax steht am Anfang sowohl der Typ (den PHP sonst nur implizit erkennen kann) als auch die Länge, unserialize muss also nur noch x Bytes lesen, ohne sie sich anzuschauen.
Ähm aah hm, ok so weit habe ich natürlich nicht gedacht. Aber wo du recht hast hast du recht.
Ich habe das grade mal getan und es bestätigt meine Intuition (auch wenn der Unterschied schwächer ausfällt, als vermutet):
Ok, danke ich bin überzeugt ;-).
Grüße
Jeena Paradies
Hello,
wenn Du für die Besucher eine Session führst, dann kannst Du die Datei auch als Array in der Session ablegen. Das belastet Dein Script (den Speicherverbrauch) wahrscheinlich nicht mehr, als wenn Du parse_ini_file() jedesmal aufrufst. Allerdings bedarf es dann eben einer IO-Operation weniger, wenn Du _sowieso_ eine Session führst.
Du könntest auch shared Memory in Anspruch nehmen. Du benötigst dann eben nur eine Möglichkeit, das Handle auf den Memorybereich weiterzugeben. Wenn Du es verlierst, wird Dein Speicher eben langsam aufgefressen. Ich habe jetzt nicht nachgeschaut, aber er wird dann wohl dem Apachen gehören, der aber selber keine Handles darauf hat. Du kannst dann nur den Webserver neustarten ...
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hello,
und schau Dir mal die Erklärung auf
http://de.wikipedia.org/wiki/Einzelstück_(Entwurfsmuster)#Implementierung_in_PHP_.28ab_Version_5.29
an.
Wesentlich ist doch mMn, dass Du die Instanz von einem Script zum anderen weitertragen willst, oder?
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hallo,
danke für die Hilfe.
Mal schauen welche Lösung ich nehmen werde.
Bin eigentlich anfangs davon ausgegangen, dass das eingelesene file einmal im Arbeitsspeicher abgelegt wird und dann immer darauf zugegriffen werden kann. Aber offensichtlich kennt das php gar nicht?!
Vielleicht versuche ich auf einfach alles in eine Datei zu machen die ich dann include.
Vielleicht noch eine Frage:
Wenn ich das Array in die Session ablege, wird dann nur in der Session eine Referenz auf das Array oder alle Daten des Arrays übergeben?
Danke und Grüße
Bene
hi,
Wenn ich das Array in die Session ablege, wird dann nur in der Session eine Referenz auf das Array oder alle Daten des Arrays übergeben?
Das Array wird komplett in der Session abgelegt.
Übergeben - vom Server an den Client, und vom dem wieder zurück an den Server - wird immer nur die Session-ID.
gruß,
wahsaga
echo $begrüßung;
Bin eigentlich anfangs davon ausgegangen, dass das eingelesene file einmal im Arbeitsspeicher abgelegt wird und dann immer darauf zugegriffen werden kann. Aber offensichtlich kennt das php gar nicht?!
Das liegt nicht an PHP sondern an HTTP. Jeder Request wird einzeln und für sich selbst abgearbeitet. Von anderen Requests bekommt er nichts mit. Um diese "Unzulänglichkeit" von HTTP auszugleichen, und Daten requestübergreifend zu sichern ist z.B. der Session-Mechanismus erfunden worden.
Wenn ich das Array in die Session ablege, wird dann nur in der Session eine Referenz auf das Array oder alle Daten des Arrays übergeben?
Die Daten werden zum Script-Abschluss serialisiert und in einer Datei abgelegt. Beim Wiedereröffnen der Session wird diese Datei geparst und die Variablen werden neu angelegt. Du kannst davon ausgehen, dass zwischen zwei Requests von PHP und den ausgeführten Scripts nichts im Speicher verbleibt. (Diese Aussage ist zwar nicht ganz korrekt, das tut hier aber nichts zur Sache. Jedenfalls gibt es keine Garantie für deine Scripte, dass irgend etwas aus früheren Inkarnationen im Speicher überlebt.)
Diese Session-Dateien kann man sich mit einem Textanzeigeprogramm ansehen. phpinfo() sagt dir über session.save_path wo PHP diese Dateien ablegt.
Das Parsen der Session-Datei und parse_ini_file() werden sich vermutlich geschwindigkeitsmäßig nicht viel nehmen.
echo "$verabschiedung $name";
Hello,
Bin eigentlich anfangs davon ausgegangen, dass das eingelesene file einmal im Arbeitsspeicher abgelegt wird und dann immer darauf zugegriffen werden kann. Aber offensichtlich kennt das php gar nicht?!
PHP sollte das auch können http://de.php.net/manual/en/ref.shmop.php
Ich habe aber noch nicht damit gearbeitet.
Ich weiß daher nicht, inwieweit man das Handle von einem Prozess an den anderen weitergeben kann. Das hängt davon ab, wem die Handle-Tabelle gehört. Die sollte dem PHP-Stammprozess im Apachen gehören, dann klappts auch mit den Schwester- und Kindprozessen ;-)
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hallo,
danke für die Antworten.
Wieder was dazugelernt.
grüße
bene
Moin!
ich habe in einer Config Datei alle Texte die ich auf der Website einsezten will, wie kurze Erläuterungen, etc. Da die Texte von anderen gepflegt werden müssen, muss ich sie auslagern. Ich greife dann mit der Funktion parse_ini_file darauf zu.
Das klingt eigentlich so, als wären diese Texte ein Kandidat für die Internationalisierungs- bzw. Lokalisierungsfunktionen in PHP, die sich hinter gettext verbergen.
- Sven Rautenberg