Machbarkeit Multiple-File-Access aus einer Thread Applikation



  • PHP fread gegen C fread, hab ich noch nie probiert. Dürfte aber wohl auf denselben Systemcall gehen.
    Der numblock Parameter von fread/fwrite sollte aus Performanzsicht immer auf 1 stehen (bei bekannter Gesamtgröße), du machst genau das Gegenteil.
    Das setvbuf lasse erstmal weg, bei Multithreads weiß das Betriebssystem eh besser über Filecaching Bescheid als du in deinem Thread.
    Hast du schon mal über einen Threadpool nachgedacht?
    Nehme erstmal 1 Thread und tune diesen für ein paar realitätsnahe Terabytes, multithreaden kannst du dann immer noch.
    Ich bin auch der Meinung, die C Variante sollte schneller und weitaus ressourcenschonender sein als PHP, meine C Programme waren dies gegenüber irgendwelchen Skriptsprachen bisher jedenfalls immer 😉



  • PHP erzeugt intern einen "PHP-Stream", der aber allem Anschein nach wieder mit MMAP oder fread arbeitet (MMAP scheinbar für kleinere Operationen, ganz schlau bin ich aus dem Code durch Portabilität der PHP-Sourcen nicht geworden).

    Die Blockangabe war mir als Fehler komplett nicht klar 😕, vielen Dank für den Tip. Die Änderung mache ich gleich klar und berichte dann.

    Mit einem Thread hatte ich es mittels Lighttpd getestet, da dieser die Prozesse selber bis zur Menge X ausspannen kann. Allerdings läuft Lighty dank der fehlenden Blockade des FastCGI Puffers irgendwann voll. Bisher konnte ich keine Möglichkeit für FastCGI finden, wie man herausfindet, ob der Webserver schon für den User zwischenpuffert, oder auf weitere Daten wartet. Bei NGINX passiert genau dieser Sachverhalt nicht, ich konnte aber hier bisher keine Single-Prozesse direkt nutzen, da die FastCGI-Api dort immer einen Multithread-Prozess zu erwarten scheint.
    Mit einem Threadpool meinst du die Reader für die Dateien? Ich hatte als Test einen Pool von Reader-Threads erzeugt, welche den eigentlichen Threads für die Ausgabe die Daten geliefert haben. Das Ergebnis war vergleichbar mit den aktuell auskommentierten Mutex's.

    Da die Umsetzung für die Änderung des Projekts von mir kam, geht es auch um die Meinung "das muss doch schneller sein" ;-). Sparsamer ist es in jedem Fall, da die meist 300x22MB Apache + PHP-Modul einfach den RAM unnötig überreizen.

    EDIT:
    bringt auch leider keinen Unterschied. Aber selbst ein Test mittels Lighttpd bringt bei 200 laufenden Prozessen selbiges Ergebnis:
    Das RAID geht unter der aggressiven Menge von Anfragen nach ein paar Minuten unter.
    Auch mit iotop und lsof sieht man lediglich die offenen Dateien/Anfragen nach Daten. Für mich wirken diese Anfragen aber wesentlich aggressiver, als die des PHP-freads. Als ob das eingesetzte Readahead des Kernel überhaupt nicht greifen würde.
    Bei einem Blockdev -setra 16384 /dev/sda sehe ich via iotop z.b. für jeden Apache-Prozess immer konstante Anfragen von 8MB/s, bei einer Erhöhung auf 32768 werden passend 16mb/s verlangt.
    Meine eigenen Prozesse fragen quer alles an. Mal große Mengen mit passenden Angaben zum readahead, mal Kilobyte-Mengen, die mir gar nicht einleuchten.
    (Die Aussagen beziehen nur auf die ersten Sekunden/Minuten solange das RAID noch sauber liefern kann, danach bricht sowieso die gelieferte Menge an Daten zusammen und die Prozesse bekommen nur noch Kilobyte-Mengen).



  • Ich bin mir jetzt nicht sicher wie viel FastCGI dir da an Arbeit abnimmt, aber hast du die Möglichkeit eine Verbindung direkt über Sockets herzustellen?



  • cooky451 schrieb:

    Ich bin mir jetzt nicht sicher wie viel FastCGI dir da an Arbeit abnimmt, aber hast du die Möglichkeit eine Verbindung direkt über Sockets herzustellen?

    Der Spezialist wieder. 😃



  • Hallo,

    FastCGI dient eigentlich "nur" (Soll nicht abwertend klingen, mir fällt nur nichts besseres ein ;)) die Verbindung zum Weserver her. Die Idee selber einen aufzusetzen war in jedem Fall im Raum, aber die Faulheit hat am Ende gesiegt, da der Aufwand doch nicht zu unterschätzen wäre.

    Den Tag über bin ich weiterhin am testen und konnte mittels dem normalen open und read mit einem posix_fadvice für sequentielles lesen bei einem Puffer von 16MB ein recht ruhig laufendes System erstellen, welches aber durch sich überlappende "Nachlade-Threads" (aktuell limitiert auf 12) immer wieder kurz ins Wackeln und Stocken gerät.

    Gibt es ausser den Beschreibungen von GNU.org und den Linux Dokus noch andere Quellen, an denen man sich mit Themen wie dem Read-Ahead auseinandersetzen kann?
    Mir leuchtet weiterhin die Kunst nicht ein, mit welcher einmal bei wesentlich geringerer Blockgröße (Apache-PHP) ein ruhig laufendes System entsteht, und an anderer Stelle mit den vermeindlich gleichen Werkzeugen bei sogar größerer Blockgröße/Puffer eine recht große Systemlast entsteht. Das Finetuning hierfür ist allerdings für mich in den PHP-Quellen nicht so einfach ersichtlich :(.



  • Nur ums mal in den Raum zu werfen: Hast du schon von HipHop gehört?



  • Nabend ;),

    ja, in der Tat, Hiphop hatten wir im Gespräch. Es scheiterte aber der fehlenden Threadfähigkeit um wiederum von NGINX angesteuert zu werden. Mir ist auch bis heute kein Weg bekannt wie man eine auf einen Socket höhrende Anwendung in PHP schreiben könnte, die dann Anfragen auf verschiedene Threads verteilt.
    Ansonsten juckt mich gerade die Möglichkeit nach dem Komplieren die Lesefähigkeiten zu testen (ob diese überhaupt noch in der gleichen Form vorhanden sind).



  • Ich würde ja gerne etwas beisteuern, aber mit meiner 100Mbit LAN Leitung schaffe ich es nicht mal auf 1% Prozessorauslastung zu kommen, da gestalten sich Tests irgendwie schwierig. 🙄



  • Auch nach dem Wochenende bin ich nicht schlauer.

    Aber ggf. weiss jemand von Euch eine Antwort auf diese Frage ;):

    Muss ich unter Linux bei Verwendung des GCC den Read-Ahead anders ansteuern als den systemweiten, welcher quasi jede Applikation bedient (die auch in C geschrieben ist)?

    Meiner Meinung nach sollte der systemweite (via blockdev oder /proc eingestellt) den Apache in gleichen Bereichen beeinflussen wie eine normale C-Applikation die mittels (f)open an Dateien rangeht (wie meine).
    Um genau das zu testen habe ich gestern unter großerer Last PHP nachgeahmt und schlicht und einfach mittels read() (ohne jeden advice an den Kernel) 512kb Daten blind an den Webserver geschickt. Das Ergebnis war im Gegensatz zu den PHP reads ein vollkommen zappeliger Server, welcher nach ein paar Minuten auf 100%wa war.

    Irgendwas lässt mich nicht los, dass das Read-Ahead überhaupt nicht funktioniert. Die Doku von GNU sagt zum GGC absolut nichts aus was darauf passt. Lediglich die posix_fadvice sind verzeichnet, aber wohl auch nicht zwingend notwendig (bringen aber auch keine Besserung wenn man sie in meinem Fall verwendet).



  • Guten Abend!

    Die "Lösung" für das Problem war ein erneutes Lesen der PHP-Stream Sourcefiles. In einem Kommentar stand etwas wie "Check if buffer is already filled".

    Die PHP-Macher haben ein Thread-basiertes Backgrounding zum Cachen implementiert.
    Der Aufwand dafür war mir schlicht zu groß, aber für den GCC gibt es die AIO-Lib (Async Input/Output http://lse.sourceforge.net/io/aio.html), welche quasi genau das Verhalten ermöglicht.

    Zusätzlich lässt sich die Priorität des Reader senken, das Ergebnis ist ein sehr ruhig laufender Lesevorgang, welcher minimal so gut ist wie der von PHP, allerdings mit einer stark gesteigerten RAM-Kontrolle für die Caches und einen Speichergewinn durch die fehlenden PHP-Parser und den Webserver.

    Danke an alle Beteiligten für die ganzen Denkanstöße ;-).


Anmelden zum Antworten