Fred: fgets / fread / ..

hallo,

wenn ich eine datei via fgets/fread/.. stück für stück einlese und sie direkt ausgebe wächst die virtuelle speicherauslastung vom apache endlos an und wird selbst nach ende der verarbeitung nicht freigegeben.

weiss einer wieso das so ist? und viel wichtiger, wie man es verhinden kann?

flush/clearstatscach/... haben keine lösung gebracht.

file_get_contents/readfile kann ich nicht nutzen, da hier ab einer bestimmten dateigröße >50MB oftmals der ganze apache abstürzt bzw. die verarbeitung einfach hängen bleibt und keine anfragen mehr bearbeitet werden.

der verwendete code:

$fp = fopen($file,"rb");
while (!feof($fp)) {
   echo fgets($fp, 4096);
}
fclose($fp);

grüße Fred

  1. Hallo!
    ich wuerde mal fread($fp, filesize(<file>)), zum auslesen verwenden, aber ich glaube es liegt viel mehr an der grossen Dateigroesse, dass dein PC lahm wird. Es ist nun nicht normal 50mb grosse Dateien zu oeffnen, was haette das auch fuer einen Sinn fuer den Clienten, der Stunden warten muesste, biss die Datei geoeffnet waere.
    Warum brauchst du so grosse Dateigroessen?
    Dein Bastian

    1. die erwähnung der abbrüche bezieht sich nur auf die großen datein wenn man sie mit readfile/file_get_contents einliest. das der speicher nicht mehr freigegeben wird ist dabei größenunabhängig und eben dieses problem will ich lösen.

      auf die frage wieso die datein solche größen annehmen können sollen:
      ein filemanager mit zugriffsschutz, jeder dateizugriff wird protokoliert und nur sofern die notwendigen rechte vorhanden sind zum auslesen (download) erlaubt. (auf internet/intranet ebene)

      selbst wenn ich fread() nutzen würde und mit fseek stück für stück durch die datei navigiere um das problem sofortigen überladens und damit des absturzes zu umgehen, wird der speicher belegt und ebenfalls nicht freigegeben.

      aber wieso? und wie kann ich dieses problem lösen?

      @dann müsste der client stunden warten wenn die datein so gross sind:
      sowas kann man schlecht verhindern, wenn datein groß sind, sind sie nunmal große.

      grüße Fred

      1. Hello,

        darüber solltest Du dich mal mit CK unterhalten *gg*

        Aber prinzipiell ist es so, dass die Dateizugriffe mittels fread bei PHP automatisch bufferd werden. Es handelt sich hierbei nicht um einen "normalen" Filebuffer, sondern so eine third-level-cache, also einen PHP-internen Zwischenspeicherbereich.

        Dieser wird erst wieder frei gegeben, wenn dafür eine Notwendigkeit besteht, Teile länger nicht mehr benutzt wurden oder ein fclose() auf das Handle ausgeführt wird. Außerdem sollte man natürlich darauf achten, dass man als Lesebuffer in der Leseschleife immer dieselbe Variable benutzt, damit diese nicht auch noch über alle Grenzen wächst...

        Wenn Du knapp mit Speicher bist, dann benutze die dio_*-Funktionen von php, die aber nur funktionieren, wenn mit --enable-dio oder --with-dio kompiliert wurde. Musst Du nochmals nachlesen.

        Die Direct Input Output Funktionen haben aber nur dann Sinn, wenn man mit Mandatory Locking und Random-Access Files mit harmonisierten Buffer-Größen arbeiten will.

        Harzliche Grüße aus http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. das der buffer/speicher nur freigegeben wird, wenn er andersweitig benötigt wird, ist recht verständlich und auch üblich. nur ist bei meinem fall auffällig das der speicher nicht freigegeben wird (eine eigene variablen-bufferung mache ich nicht, direktes echo).
          bei weiteren test is allerdings auffällig das der fehler nur bei der php 4 version auftritt, bei php 5 arbeitet alles genauso wie es soll, der speicher wird zwar ebenfalls nicht dirket freigegeben, wird aber bei mehrfachausführugn auch nicht doppelt und dreifach bis zum buffer-overflow und dann folgenden apache-crash belagert.

          an mangelnden speicher liegts net, der rechner hat 768MB ram und 1,5gb vram. die auslastung bei php4 und fgets/fread ist dann aber bei dem testfile mit 450MB nach drei downloads bis zum abschließenden apache-crash zu schnell erreicht.

          kanns sein, das php4 an der stelle nen bug hat?

          dio is derzeit net einkombiliert, bin auch kein kombilierprofi... insofern kann das nen stück dauern bis ich auch diese variante testen kann. die dio variabte sollte aber theoretisch helfen, wenn laut php dort wirklich alles 1:1 rausgehaun wird ohne nutzlos (zumindest in diesem fall) zu buffern.

          thx für den tip.
          grüße fred

          1. Hello,

            kanns sein, das php4 an der stelle nen bug hat?

            Deine Ausführungen hören sich eingentlich ganz fundiert an. Da möchte ich dann annehmen, dass Du leider Recht haben könntest. Hast Du da vielleicht noch eine PHP 4.0.x-Version? Die hatten nämlich anfangs etliche Bugs, die wahrscheinlich gar nicht weiter untersucht wurden dann, weil ziemlich bald eine neue Version kam.

            Solltest Du ein möglichst knappes Stück Code haben, dass diese Probleme verurschat, dann lass es mal sehen und natürlich benötgen wir auch Angaben über OS, Apacheversion und PHP-Version.

            Zur Zeit gibt es PHP 4.3.9 (unter der fünfer) und die hat eigentlich alles dabei, was man benötigt. Du nimmst Dir eigentlich nur das Configure-Tool und hängst alle alten Optionen aus der PHP-Info hinten dran, die Du wieder haben möchtest und alle neuen dazu, die Du extra haben möchtest. Die Module müssen natürlich vorhanden sein.

            Anschließend lässt Du dann make laufen und das wars auch schon.

            Von Kaspar Schweiger gibt es da eine gute Anleitung für Debian Linux und Apache und PHP. Musst Du mal googlen.

            Harzliche Grüße aus http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau