Baba: Rechenintensives Script verhindert weitere Requests

Liebe Gemeinde,

ich habe ein php-Script, welches mittels exec ein Programm aufruft (process.exe), welches sehr rechenintensiv ist. Auf meinem Laptop läuft es ca 4 Minuten. Auf dem PC ca 2.

Damit die Seite nicht minutenlang weiß zeigt, habe ich das ganze in ein php-Script ausgelagert, das ich mittels AJAX aufrufe. Klappt soweit super.

Nur kann ich jetzt zum Beispiel nicht:
a) einen neuen Tab öffnen und weiterbrowser
b) einen weiteren AJAX Request zum Script alle 2 Sekunden starten

Das Problem wurde mir klar, als ich versuchte, sowas wie 2) zu realisieren, um den Fortschritt zu erfassen. process.exe schreibt einen Index von 1-600 in eine Textdatei und mit diesem wollte ich eine Fortschrittsanzeige realisieren. Nur kommt dieses zweite Script gar nicht zu dem Server durch, solange nicht das erste Script gelaufen ist. Dies habe ich mit Firebug rausgekriegt.

Die Frage nun:

  • warum kann ich keine weiteren Requests von außerhalb auf die Website machen
  • wie kann ich auf dem Server die Ressourcen besser verwalten.

Ich benutze WAMP als Server.

Cheers,
Baba

  1. Hallo,

    Das Problem wurde mir klar, als ich versuchte, sowas wie 2) zu realisieren, um den Fortschritt zu erfassen. process.exe schreibt einen Index von 1-600 in eine Textdatei und mit diesem wollte ich eine Fortschrittsanzeige realisieren. Nur kommt dieses zweite Script gar nicht zu dem Server durch, solange nicht das erste Script gelaufen ist. Dies habe ich mit Firebug rausgekriegt.

    Bist du dir da sicher? Ich würde vermuten das das zweite script nicht auf die Datei zugreifen kann, solange das erste Script darin rumschreibt und deshalb wartet, bist das erste script fertig ist. Vielleicht kommt der Request ja beim Server an. Nun sendet der halt nichts zurück.

    Viele Grüße Novi

    --
    "(...) deshalb mag ich Binärtechnik. Da gibt es nur drei Zustände: High, Low und Kaputt." (Wau Holland)
    1. Bist du dir da sicher? Ich würde vermuten das das zweite script nicht auf die Datei zugreifen kann, solange das erste Script darin rumschreibt

      Vielen Dank für Deine Antwort.

      Was Du schreibst macht Sinn für diesen Fall. Und ich kann derzeit nicht rausfinden, ob der externe Prozess den Handler auf die Indexdatei nie schliesst.  Aaaaaaaber: müsste dann nicht 1) ohne Probleme gehen? (Einen neuen Tab der Website öffnen.)

      Habe gerade noch etwas bemerkt. Der Server generell ist wohl nicht zu busy. Vielleicht kann mir nochmal einer helfen.

      Wenn ich während des langen Prozesses die index.php öffnen will (Startseite) geht das nicht, bis der lange Prozess fertig ist. Wenn ich allerdings zB. playground.php öffenen will, geht das sofort.

      Die Seite, die den Ajax beinhaltet ist index.php/matlab2. Es ist eine völlig andere Seite, die aber über die index.php geht. Alle Seiten gehen bei mir über die index.php

      Das Ziel des Ajax Requests ist route.php

      Kann es sein, dass während des langen Prozesses die index.php geblockt ist?

  2. Moin!

    Das Problem wurde mir klar, als ich versuchte, sowas wie 2) zu realisieren, um den Fortschritt zu erfassen. process.exe schreibt einen Index von 1-600 in eine Textdatei und mit diesem wollte ich eine Fortschrittsanzeige realisieren. Nur kommt dieses zweite Script gar nicht zu dem Server durch, solange nicht das erste Script gelaufen ist. Dies habe ich mit Firebug rausgekriegt.

    Ist eine Session aktiv? Dann setzt jedes Skript ein Lock auf die Session, damit sich zwei gleichzeitige Skripte nicht unsachgemäß die Daten zerstören - als Effekt werden alle Skripte auf dieselbe Session seriell abgearbeitet.

    session_write_close() wäre eine Alternative. Damit schreibst du die Session weg und schließt die Session-Datei. Danach kannst ein anderes Skript die Session weiterführen. Allerdings hat das erste Skript danach keine Möglichkeit mehr, noch was in die Session zu speichern.

    - Sven Rautenberg

    1. Ist eine Session aktiv? Dann setzt jedes Skript ein Lock auf die Session, damit sich zwei gleichzeitige Skripte nicht unsachgemäß die Daten zerstören - als Effekt werden alle Skripte auf dieselbe Session seriell abgearbeitet.

      Wow, ich liebe dieses Forum einmal mehr. Ich hatte keine Idee mehr.

      Also, das erklärt einiges. Ja, es ist eine Session aktiv. Und bei jenem playground-script, was sich laden lässt, wird eben keine gestartet. Das erklärt auch, warum ich mit einem anderen Browser parallel zugreifen kann.

      Ich werde das morgen, ausgeschlafen sofort probieren.

      Vielen lieben Dank.
      Grüße,
      Baba

      1. Hello,

        Ist eine Session aktiv? Dann setzt jedes Skript ein Lock auf die Session, damit sich zwei gleichzeitige Skripte nicht unsachgemäß die Daten zerstören - als Effekt werden alle Skripte auf dieselbe Session seriell abgearbeitet.

        Wow, ich liebe dieses Forum einmal mehr. Ich hatte keine Idee mehr.

        Also, das erklärt einiges. Ja, es ist eine Session aktiv. Und bei jenem playground-script, was sich laden lässt, wird eben keine gestartet. Das erklärt auch, warum ich mit einem anderen Browser parallel zugreifen kann.

        Zwei Browser -> i.d.R. zwei unterschiedliche Sessions. Die beißen sich also nicht.

        Selber Browser -> i.d.R. begrenzt auf z.B. 2 (oder auch 8, je nach Browser) offene Requests pro Domain. Das kann man am Browser zwar meistens konfigurieren, aber das Konfigurieren kann man schlecht von jedem User verlangen...

        Alternative:
        Das rechenintensive Script per ecec() in den Hintergrund stellen. Dort läuft das dann auch weiter, ohne dass die Browserseite noch offen ist. Da kannst Du dann gelegentlich nachfragen (per Ajax), wie weit es schon gediehen ist.

        Im Archiv findest Du eine Reihe von Beiträgen zum Thema

        z.B.:
        http://forum.de.selfhtml.org/archiv/2007/1/t145034/#m941113
        http://forum.de.selfhtml.org/archiv/2007/3/t149507/#m971082

        usw.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Moin!

          Hello,

          Ist eine Session aktiv? Dann setzt jedes Skript ein Lock auf die Session, damit sich zwei gleichzeitige Skripte nicht unsachgemäß die Daten zerstören - als Effekt werden alle Skripte auf dieselbe Session seriell abgearbeitet.

          Wow, ich liebe dieses Forum einmal mehr. Ich hatte keine Idee mehr.

          Also, das erklärt einiges. Ja, es ist eine Session aktiv. Und bei jenem playground-script, was sich laden lässt, wird eben keine gestartet. Das erklärt auch, warum ich mit einem anderen Browser parallel zugreifen kann.

          Zwei Browser -> i.d.R. zwei unterschiedliche Sessions. Die beißen sich also nicht.

          "In der Regel"!?!

          Selber Browser -> i.d.R. begrenzt auf z.B. 2 (oder auch 8, je nach Browser) offene Requests pro Domain. Das kann man am Browser zwar meistens konfigurieren, aber das Konfigurieren kann man schlecht von jedem User verlangen...

          Wieviele Connections der Browser zum Server öffnet, ist egal. Die Grenze liegt bei einem Wert größer als 1. Also sind parallele Requests möglich und technisch auch erwünscht.

          Aber wenn der Server die Abarbeitung eines Requests solange pausiert, bis das Session-File entsperrt ist, bringt das nichts.

          Alternative:
          Das rechenintensive Script per ecec() in den Hintergrund stellen. Dort läuft das dann auch weiter, ohne dass die Browserseite noch offen ist. Da kannst Du dann gelegentlich nachfragen (per Ajax), wie weit es schon gediehen ist.

          Das Verlagern eines zeitaufwendigen Tasks in den Hintergrund hat denselben Effekt, wie das vorzeitige Wegschreiben und Freigeben des Session-Files.

          Mit dem Vorteil, dass der Browser weiterhin mit Infos über den Fortgang versorgt werden könnte, aber am Ende eben kein Update der Session mehr stattfinden kann.

          Im Archiv findest Du eine Reihe von Beiträgen zum Thema

          z.B.:
          http://forum.de.selfhtml.org/archiv/2007/1/t145034/#m941113
          http://forum.de.selfhtml.org/archiv/2007/3/t149507/#m971082

          usw.

          Das Problem hier ist Session-Locking. Davon schon mal gehört? Locking ist doch sonst dein Lieblingsthema, Nebenläufigkeit etc.

          Locking wird übrigens gern vergessen, wenn man die Session-Daten lieber in einer Datenbank ablegen will.

          - Sven Rautenberg

          1. Hello,

            Das Problem hier ist Session-Locking. Davon schon mal gehört?

            warum so giftig?

            Das Problem liegt ganz woanders, nämlich im Fehlen einer vernünftigen Planung für die Lösung der Aufgabe.

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Das Problem liegt ganz woanders, nämlich im Fehlen einer vernünftigen Planung für die Lösung der Aufgabe.

              Bitte kläre mich auf.

              Cheers,
              Baba

              1. Moin!

                Das Problem liegt ganz woanders, nämlich im Fehlen einer vernünftigen Planung für die Lösung der Aufgabe.

                Bitte kläre mich auf.

                Offensichtlich hat Tom daran kein Interesse mehr.

                - Sven Rautenberg

                1. Hello Baba & Sven,

                  Das Problem liegt ganz woanders, nämlich im Fehlen einer vernünftigen Planung für die Lösung der Aufgabe.

                  Bitte kläre mich auf.

                  Offensichtlich hat Tom daran kein Interesse mehr.

                  Das ist nicht "offensichtlich", sondern "vermutlich". Für ein "offensichtlich" sind die Indizien keinesfalls hinreichend. Oder kurz: ich ahbe es einfach nicht gesehen, dass hier noch eine reaktion kam.

                  Zum Thema:
                  Ich hatte in https://forum.selfhtml.org/?t=208288&m=1416282 schon erwähnt, dass es sinnvoller sein kann, das rechnenintensive Script auf dem Server in den Hintergrund zu stellen und es dann ggf. von Zeit zu Zeit dessen Zustand durch einen _kurzen_ Kontrollrequest abzufragen.

                  Dazu muss das Script selbstverständlich geeignet geschrieben sein. Die notwendigen Sessiondaten werden beim Start als Parameter oder in einer separaten Datei übergeben. In dieser separaten Datei kann das Script dann auch den Zustand melden.

                  Die Verbindung zur Standardausgabe zu halten kostet nach meinen Erfahrungen viel mehr Kraft bzw. Zeit, als eine Ausgabe in eine Datei zu lenken. Woran das liegt, habe ich nicht untersucht, vermute aber, dass es nicht anders ist, als beim guten alten DOS. Viele Umlenkungen kosten eben.

                  Warum soll ich also den Client blockieren und - viel wichtiger - einen Kanal vom Client zum Server dauerhaft blockieren, wenn es mit kurzen Kontrollrequests auch geht?

                  Baba sollte sich für derartige Vorgänge ein ausführliches Zeit-Aufgaben-Diagramm erstellen und erst dann "AJAX" oder andere Wunderwaffen einsetzen, wenn diese aufgrund guter Planung so kurz wie möglich eingesetzt werden können - dafür lieber öfter.

                  Es ist nicht sinnvoll, Verbindungsorientierung bei HTTP durch Gewalt herzustellen. Es ist besser, diese durch Logik nachzubilden.

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
                  1. Hello,

                    Es ist nicht sinnvoll, Verbindungsorientierung bei HTTP durch Gewalt herzustellen. Es ist besser, diese durch Logik nachzubilden.

                    Sollte eigentlich besser heißen:
                    ... Zustandsorientierung durch erzwungene Verbindungsorientierung herzustellen. Es ist besser, die Zustandsorientierung durch Logik nachzubilden.

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                     ☻_
                    /▌
                    / \ Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
        2. Alternative:
          Das rechenintensive Script per ecec() in den Hintergrund stellen.

          exec() wartet aber auf den Prozess standardmäßig. Die Foren sind voll davon, dass es nicht gelingt "die Ausgabe umzulenken". Da das ganze auf jedem OS auch noch anders ist, habe ich es gleich verworfen. Auch weil einige Stimmen sagen, das php dafür nicht das richtige Werkzeug ist, und es besser ist, das nicht zu erzwingen.

    2. Dann setzt jedes Skript ein Lock auf die Session, damit sich zwei gleichzeitige Skripte nicht unsachgemäß die Daten zerstören - als Effekt werden alle Skripte auf dieselbe Session seriell abgearbeitet.

      session_write_close() wäre eine Alternative. Damit schreibst du die Session weg und schließt die Session-Datei. Danach kannst ein anderes Skript die Session weiterführen. Allerdings hat das erste Skript danach keine Möglichkeit mehr, noch was in die Session zu speichern.

      Juhu. Das war das Problem. Ich kriege jetzt eine schöne Anzeige (x von 600 Läufen), wie ich das wollte. Das Problem war wirklich das Session locking.

      VIELEN DANK für diesen super Tipp. Habe es mit

      @session_write_close();

      geschafft. Das @ war nötig, weil ich eine Fehlermeldung mit folgendem Wortlaut bekam, die ich nicht verstehe (da ich keinen Falls register_globals on setzen möchte):

      <fehler>
      Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off
      </fehler>

      Auch wollte ich nicht unbedingt irgendwelche Error reporting levels runtersetzen, wie

      session.bug_compat_42 = 0
      session.bug_compat_warn = 0

      in der .htaccess

      Wenn noch jemand eine Idee zu der Fehlermeldung (oder eigentlich nur dem Hinweis) hat...

      Cheers,
      Baba

      1. [...] Idee zu der Fehlermeldung (oder eigentlich nur dem Hinweis) hat...

        Du versuchst offenbar eine Variable, die mit register_globals global Gültigkeit wäre in die Session zu schreiben:

        z.B.

        $_SESSION['var'] = $var;

        oder

        $_SESSION['var'] = $_POST['var'];

        oder

        $_SESSION['var'] = 'foo';
        $var = 'bar';

      2. Moin!

        Das @ war nötig, weil ich eine Fehlermeldung mit folgendem Wortlaut bekam, die ich nicht verstehe (da ich keinen Falls register_globals on setzen möchte):

        <fehler>
        Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off
        </fehler>

        Die Fehlermeldung sagt dir, was zu tun ist, damit diese Meldung nicht kommt. :)

        Auch wollte ich nicht unbedingt irgendwelche Error reporting levels runtersetzen, wie

        session.bug_compat_42 = 0
        session.bug_compat_warn = 0

        in der .htaccess

        Googlen nach der Meldung bringt diverse Ansätze.

        1. Benutzt du session_register()?

        2. Oder weist du undefinierte Variablen an $_SESSION zu?

        Das @ ist jedenfalls keine so gute Idee, finde ich.

        - Sven Rautenberg