Ankündigung

Einklappen
Keine Ankündigung bisher.

Emulierte "Threads" per IPC

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Emulierte "Threads" per IPC

    Hallo zusammen,

    mein erster Beitrag hier im Forum und dann auch noch bei den Fortgeschrittenen, bin schon ein wenig aufgeregt!

    Also, mir geht es um das Thema Threads in PHP welche nun mal leider nicht vorhanden sind. Dafür gibt es die Möglichkeit Prozesse zu starten, stoppen und zu steuern. Somit kann man Threads in gewisser Weise emulieren.

    Vor ein paar Wochen hab ich mit der Umsetzung begonnen und mich an den Java - Threads orientiert. Nun möchte ich allen, die das Thema interessiert, die entstandenen Möglichkeiten aus der bisherigen Entwicklung aufzeigen.

    Leider ist mir kein guter Name dafür eingefallen, daher nenn ich die Klasse vorerst Thread. Es handelt sich um eine abstrakte Klasse die immer vererbt werden muss, eine instanzierbare Form ist im Moment nicht möglich. Vielleicht fällt mir dafür noch eine Lösung ein.

    Auflistung der interessantesten Methoden(aktueller Stand)
    - isAlive()
    - join($milliseconds)
    - start()
    - stop()
    - resume()
    - destroy()
    - setDaemon()
    - suspend($milliseconds)
    - isSuspended()
    - sleep()
    - dumpStack()
    - get/setPriority() [nur mit pcntl]
    - call()
    - execute()
    - wait($var, $timeout = 0)
    - waitForUpdate($var, $timeout = 0)


    Kurzer Überblick
    - Die erbende Klasse muss eine run Methode enthalten
    - Scalare, Arrays und Objekte werden vom Hauptprozess in den "Thread" Prozess gespiegelt
    - Änderungen in Objekten und Arrays werden ebenfalls gespiegelt
    - per "setDaemon()" kann ein Thread unbegrenzt lange laufen und auf Aufgaben zur Abarbeitung warten, solange mindestens ein Thread besteht beendet sich der Hauptprozess nicht
    - "call" ruft eine Methode samt Argumenten im Thread auf und liefert das Ergebnis zurück
    - "execute()" ist wie call(), nur wird nicht auf die Rückkehr gewartet
    - "wait()" lässt den Hauptprozess auf eine Variable im Thread warten und gibt den Wert aus
    - "waitForUpdate()" lässt den Hauptprozess warten bis sich der Wert einer Variablen im Thread ändert

    Die Mankos liegen auf der Hand
    - Resources können nicht gehandhabt werden
    - Redundante Datenhaltung aufgrund getrennter Prozesse

    Beispiel
    PHP-Code:
        class Runnable extends Thread
        
    {
            public function 
    run()
            {
                
    console::println('run');

                for(
    $i 0$i 10; ++$i)
                {
                    
    console::println($i);
                    
    thread::sleep(500);
                }
            }
        }


        final class 
    Test
        
    {
            public static function 
    main(array $argv$argc)
            {
                
    $r1 = new Runnable('pthread 1');
                
    $r1->start();

                
    $r2 = new Runnable('pthread 2');
                
    $r2->start();
                
    $r2->suspend(6000);

                
    $r3 = new Runnable('pthread 3');
                
    $r3->start();
                
                
    #$r1->join();
                
    $r2->join();
                
    #$r3->join();

                
    console::println('Im Main - Thread');
            }
        } 
    Code:
    Pfad...>php53 main.php
    [17.07.2009 23:37:06] thread::pthread 1~: run
    [17.07.2009 23:37:06] thread::pthread 1~: 0
    [17.07.2009 23:37:06] thread::pthread 1~: 1
    [17.07.2009 23:37:07] thread::pthread 1~: 2
    [17.07.2009 23:37:07] thread::pthread 1~: 3
    [17.07.2009 23:37:07] thread::pthread 2~: run
    [17.07.2009 23:37:07] thread::pthread 2~: 0
    [17.07.2009 23:37:08] thread::pthread 1~: 4
    [17.07.2009 23:37:08] thread::pthread 1~: 5
    [17.07.2009 23:37:09] thread::pthread 1~: 6
    [17.07.2009 23:37:09] thread::pthread 1~: 7
    [17.07.2009 23:37:09] thread::pthread 3~: run
    [17.07.2009 23:37:09] thread::pthread 3~: 0
    [17.07.2009 23:37:10] thread::pthread 3~: 1
    [17.07.2009 23:37:10] thread::pthread 1~: 8
    [17.07.2009 23:37:10] thread::pthread 1~: 9
    [17.07.2009 23:37:10] thread::pthread 3~: 2
    [17.07.2009 23:37:11] thread::pthread 3~: 3
    [17.07.2009 23:37:11] parent~: shutdown initiated
    [17.07.2009 23:37:11] thread::pthread 3~: 4
    [17.07.2009 23:37:12] thread::pthread 3~: 5
    [17.07.2009 23:37:12] thread::pthread 3~: 6
    [17.07.2009 23:37:13] thread::pthread 2~: 1
    [17.07.2009 23:37:13] thread::pthread 3~: 7
    [17.07.2009 23:37:13] thread::pthread 2~: 2
    [17.07.2009 23:37:13] thread::pthread 3~: 8
    [17.07.2009 23:37:14] parent~: thread pthread 1 - shutdown complete
    [17.07.2009 23:37:14] thread::pthread 2~: 3
    [17.07.2009 23:37:14] thread::pthread 3~: 9
    [17.07.2009 23:37:14] thread::pthread 2~: 4
    [17.07.2009 23:37:14] parent~: shutdown initiated
    [17.07.2009 23:37:15] thread::pthread 2~: 5
    [17.07.2009 23:37:15] thread::pthread 2~: 6
    [17.07.2009 23:37:16] thread::pthread 2~: 7
    [17.07.2009 23:37:16] thread::pthread 2~: 8
    [17.07.2009 23:37:17] parent~: thread pthread 3 - shutdown complete
    [17.07.2009 23:37:17] thread::pthread 2~: 9
    [17.07.2009 23:37:17] parent~: Im Main - Thread
    [17.07.2009 23:37:17] parent~: shutdown initiated
    [17.07.2009 23:37:20] parent~: thread pthread 2 - shutdown complete
    [17.07.2009 23:37:20] parent~: shutdown complete
    Analyse der Ausgabe
    * Thread 1 startet und schafft 4 Ausgaben vor dem Start von Thread 2
    * Thread 2 macht eine Ausgabe, dann wird es vom suspend(6000) für 6 Sekunden schlafen gelegt.
    * Thread 1 + 3 laufen durch, der Hauptprozess beendet sich nicht
    * Durch $r2->join(); wird gewartet bis auch Thread 2 am Ende ist

    Meine Fragen nun an euch, was haltet ihr von der ganzen Sache, für wen ist es interessant?¿?

    Das ganze soll in ein paar Wochen OpenSource gehen. Mir schwebt da code.google oder sourceforge vor. Kann jemand einen von beiden empfehlen oder kennt ne andere gute Plattform? Im Moment tendiere ich zu google. Allerdings kommen vorher noch ein paar Erweiterungen hinzu, ThreadGroups und ThreadJobs aber das ist ein anderes Thema für später

    Achja, und ich suche noch einen guten Namen dafür, es sind Prozesse die wie Threads gehandhabt werden, vielleicht fällt euch was ein - bin für alles offen, Namensgebung, Diskussionen und Anregungen/Kritik/Erweiterung der Methoden!
    DevBlog|3D Online-Shopping|Xatrium

  • #2
    imo geht das an der idee des threads vorbei, ein Thread ist eben nur ein teil eines prozesses. interessant wird das erst, wenn der Kritische Abschnitt erreicht wird. ab da benötigst du synchrone verarbeitung, ansonsten kommt das programm zu falschen ergebnissen.
    außerdem ist das langsam ohne ende, denn für einen prozesswechsel muss der Kernel eine menge arbeit verrichten. schön sieht man die nachteile von Threademlurierung durch Prozesse bei der veralteten LinuxThread lib die mittlerweile von Native POSIX Thread Library abgelöst wurde:

    Im August/September 2002 wurde der Linux-Kernel 2.5 für die NPTL vorbereitet. Dazu war es notwendig, einige neue Systemaufrufe einzuführen und vorhandene zu optimieren. In ersten Benchmarks konnten nun auf einem IA-32-System innerhalb von 2 Sekunden 100.000 parallele Threads erzeugt werden; ohne NPTL dauerte allein die Erzeugung der Threads fast 15 Minuten. Trotz dieser bemerkenswerten Last blieb das System während dieser Tests annähernd mit normaler Geschwindigkeit benutzbar.
    schlussendlich gehe ich davon aus, das du PCNTL benutzt, oder? wenn ja, so solltest du den ersten abschnitt beachten:

    Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.
    [B]PHP4?!?[/B]>>>[B]Aktuelle[/B] PHP Version: [B]5.2.11 || 5.3.0
    [URL="http://en.opensuse.org/Factory/News"]Suse 11.2 *vorfreude*[/URL]
    [/B]

    Kommentar


    • #3
      Nein ich setze nicht auf PCNTL, es bietet zu wenig Möglichkeiten um einen Prozess in diesen Feinheiten zu steuern, zumal es so gut wie nur auf unix verfügbar ist. Lediglich die Methoden get-/setPriority() nutzen pcntl sofern auf dem System vorhanden.

      Per proc_open() wird ein Prozess gestartet, über die Pipes kommuniziert. Dies ist unter win und unix möglich. Durch ticks kann zwischen dem normalen Ablauf über die Pipes kommuniziert werden. Das BS muss sich nicht um das Handling der Prozesse kümmern, diese pausieren, stoppen, starten oder fortlaufen lassen. Das passiert im Programmablauf. Zugegeben unter Vista stirbt die Maschine bei der Prozesserstellung nahezu (vielleicht mal wieder nen Boot, der tut bekanntlich immer gut ^^), unter XP gehts recht flott und unix liegt im Millisekundenbereich.

      Das Thema Synchronisierung ist NOCH nicht aktuell, wird aber kommen wenn der Hauptprozess Zugriffe von seine Unterprozessen zulässt.

      Wie geschrieben, es sind keine Threads sondern Prozesse. Die Handhabung der Prozesskommunikation orientiert sich an der Java-Thread API. Mir fiel bisher nur kein besserer Begriff/Name ein.

      In erster Linie ist diese Entwicklung aufs CLI SAPI ausgerichtet, da ich es dafür benötige. Ich gehe aufgrund des ticks momentan nicht davon aus, dass es im Apache oder einem sonstigen Webserver läuft.
      DevBlog|3D Online-Shopping|Xatrium

      Kommentar


      • #4
        Erst heiß machen und dann hängen lassen... tztz Mich würde der Code schon interessieren. Vorallendingen wie erreichst du es das du direkt in einer Instanz einsteigen kannst? Oder interpetiere ich den Code zuviel rein?

        PHP-Code:
            class Runnable extends Thread
            
        {
            private 
        $counter 10;
            
            public function 
        setCounter($counter) {
                
        $this->counter $counter;
            }
            
                public function 
        run()
                {
                    
        console::println('run');

                    for(
        $i 0$i $this->counter; ++$i)
                    {
                        
        console::println($i);
                        
        thread::sleep(500);
                    }
                }
            }

            
            
        $test = new Runnable('foo');
            
        $test->setCounter(100);
            
        $test->run(); 
        Aber ok beim schreiben sind mir auch ein paar Ideen dazu eingefallen, aber ob die praktisch so umsetzbar sind...

        Kommentar


        • #5
          Her mit den Ideen!

          "5.3.0 Ticks are now supported on threaded web server modules." klingt gut, dann wird es auch in Apache(Worker?) & Co. laufen.

          Welche Instanz meinst du gerade, die public static function main inTest? Dafür hab ich ein Runtime Objekt welches automatisch diese besagte main Methode sucht.

          Die run() Methode der Instanz wird nicht direkt aufgerufen, sondern per start(). Im Moment entsteht der neue Prozess allerdings erst mit dem Aufruf von start(). Denke das werd ich morgen ändern. Mit der Instanz würde dann der Prozess gestartet, gehalten und wie auch immer über start() oder execute('run') angestossen werden.

          Um eine Eigenschaft zu setzen/ändern kann man eine Methode direkt aufrufen. Dann muss die Eigenschaft allerdings von der Instanz an den Prozess übergeben werden(implizit). Der elegantere Weg wäre die Methode direkt anzuweisen(explizit)

          Dein Beispiel funktioniert(implizit), so ist es ebenfalls möglich(explizit)
          PHP-Code:
             ...

              
          $test = new Runnable('foo');
              
          $test->execute('setCounter'100);
              
          $test->start(); 
          Damit ruft die Instanz die Methode setCounter samt dem Parameter '100' direkt im Unterprozess auf
          DevBlog|3D Online-Shopping|Xatrium

          Kommentar

          Lädt...
          X