Ankündigung

Einklappen
Keine Ankündigung bisher.

Suche nach Performance

Einklappen

Neue Werbung 2019

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

  • noch_anfaenger
    hat ein Thema erstellt Suche nach Performance.

    Suche nach Performance

    Hallo,

    ich suche nach besserer Performance für mein Skript.
    In
    Code:
    $data
    wird ein String gespeichert. Die Information aus diesem String soll ausgewertet werden. Mögliche Werte sind von der Art:
    Code:
    $data = "output;0FFF"
    ,
    Code:
    $data = "output;0004"
    oder
    Code:
    $data = "input;ON"
    oder
    Code:
    $data = "input;OFF"
    Dabei nach "output" steht immer eine hexadezimale Zahl: "0FFF", "0004" oder eine andere.
    PHP-Code:
    <?
    $var = substr($data,0,6); // In $var steht 'output' oder 'input;'
    $hex = substr($data,-5); 

    //Auswerten und Setzen der Outputs
    // Z.B. $data = output;0008
    if ($var == 'output') {
            SetValueString($id_gerät, $hex);
            $bin = base_convert($hex, 16, 2); //Konvertiere hexadezimale Zahl nach binäre. 
    //Die führenden Nullen werden abgeschnitten (z.B. statt 001001 bekommt man 1001)
            //echo "binär ".$bin."\n";
            $str = (string)$bin; // Typumwandlung nach String
            $arr = array();
            
            if (strlen($str) < 12) { // Wenn die führenden Nullen abgeschnitten sind, dann hänge die 
    //am Anfang des Strings
                switch(strlen($str)) {
               case 1:
               $str = "00000000000".$str;
               break;
               case 2:
               $str = "0000000000".$str;
               break;
               case 3:
               $str = "000000000".$str;
               break;
               case 4:
               $str = "00000000".$str;
               break;
               case 5:
               $str = "0000000".$str;
               break;
               case 6:
               $str = "000000".$str;
               break;
               case 7:
               $str = "00000".$str;
               break;
               case 8:
               $str = "0000".$str;
               break;
               case 9:
               $str = "000".$str;
               break;
               case 10:
               $str = "00".$str;
               break;
               case 11:
               $str = "0".$str;
               break;
            }
        }
            
            for ($i = 0; $i < strlen($str); $i++) { // Mache aus String ein Array
                array_push($arr, substr($str, $i, 1));
            }
            $arr_rev = array_reverse($arr); // Setze Elemente im Array in umgekehrter Reihenfolge
            foreach($arr_rev as $key => $value) { // Kucke, an welchen Stellen die Einsen 
    //und an welchen Nullen stehen
                if ($value == 1) {
                
                switch ($key) {   // Key steht hier für port_out
                     case "0":
                    SetValueBoolean($id_0, true);
                    break;
                    case "1":
                    SetValueBoolean($id_1, true);
                    break;
                    case "2":
                    SetValueBoolean($id_2, true);
                    break;
                    case "3":
                    SetValueBoolean($id_3, true);
                    break;
                    case "4":
                    SetValueBoolean($id_4, true);
                    break;
                    case "5":
                    SetValueBoolean($id_5, true);
                    break;
                    case "6":
                    SetValueBoolean($id_6, true);
                    break;
                    case "7":
                    SetValueBoolean($id_7, true);
                    break;
                    case "8":
                    SetValueBoolean($id_8, true);
                    break;
                    case "9":
                    SetValueBoolean($id_9, true);
                    break;
                    case "10":
                    SetValueBoolean($id_10, true);
                    break;
                    case "11":
                    SetValueBoolean($id_11, true);
                    break;
                }
            }
            else {
             switch ($key) {   // Key ist port_out
                     case "0":
                    SetValueBoolean($id_0, false);
                    break;
                    case "1":
                    SetValueBoolean($id_1, false);
                    break;
                    case "2":
                    SetValueBoolean($id_2, false);
                    break;
                case "3":
                    SetValueBoolean($id_3, false);
                    break;
                    case "4":
                    SetValueBoolean($id_4, false);
                    break;
                case "5":
                    SetValueBoolean($id_5, false);
                    break;
                    case "6":
                    SetValueBoolean($id_6, false);
                    break;
                    case "7":
                    SetValueBoolean($id_7, false);
                    break;
                    case "8":
                    SetValueBoolean($id_8, false);
                    break;
                    case "9":
                    SetValueBoolean($id_9, false);
                    break;
                    case "10":
                    SetValueBoolean($id_10, false);
                    break;
                    case "11":
                    SetValueBoolean($id_11, false);
                    break;
                }
            }
        }
    }
    //Auswerten und Setzen der Inputs
    // Z.B. $data = input4;ON

    else {
      $port_in = substr($data, 5, 1); // Hier wird eine Nummer extrahiert, in diesem Fall $port_in = 4
       $status_in = substr($data, 7, strlen($data)-7); // Hier $status_in = ON
       echo $port_in."\n";
       echo $status_in."\n";
        SetValueString($id_gerät, $status_in);
        if (trim($status_in) == 'ON') {
            switch ($port_in) {
             case "0":
                SetValueBoolean($id_0 , true);
                break;
                case "1":
                SetValueBoolean($id_1 , true);
                break;
                case "2":
                SetValueBoolean($id_2 , true);
                break;
                case "3":
                SetValueBoolean($id_3 , true);
                break;
                case "4":
                SetValueBoolean($id_4, true);
                break;
                case "5":
                SetValueBoolean($id_5 , true);
                break;
                case "6":
                SetValueBoolean($id_6, true);
                break;
                case "7":
                SetValueBoolean($id_7, true);
                break;
                case "8":
                SetValueBoolean($id_8 , true);
                break;
                case "9":
                SetValueBoolean($id_9, true);
                break;
                case "10":
                SetValueBoolean($id_10, true);
                break;
                case "11":
                SetValueBoolean($id_11, true);
                break;
            }
        }
        else {
            switch ($port_in) {
                case "0":
                SetValueBoolean($id_0, false);
                break;
                case "1":
                SetValueBoolean($id_1, false);
                break;
                case "2":
                SetValueBoolean($id_2 , false);
                break;
                case "3":
                SetValueBoolean($id_3, false);
                break;
                case "4":
                SetValueBoolean($id_4 , false);
                break;
             case "5":
                SetValueBoolean($id_5, false);
                break;
                case "6":
                SetValueBoolean($id_6 , false);
                break;
                case "7":
                SetValueBoolean($id_7, false);
                break;
             case "8":
                SetValueBoolean($id_8, false);
                break;
             case "9":
                SetValueBoolean($id_9, false);
                break;
             case "10":
                SetValueBoolean($id_10, false);
                break;
                case "11":
                SetValueBoolean($id_11, false);
                break;
            }
        }
        
    }

    ?>
    Alles funktioniert, aber nicht ganz schnell, da es viele switch statements gibt. Ich würde mich sehr freuen, wenn jemand mir hinweist, wie ich das besser machen kann.
    Eventuell ist das mit bitweisen shift operatoren << und >> machbar. Aber wie?

  • noch_anfaenger
    antwortet
    Danke für den Hinweis!
    PHP-Code:
    function Str2Hex($daten) {
             
    $Hex "";
             for(
    $i=0$i<strlen($daten); $i++) {
                
    $Hex .= sprintf("%02X "ord($daten[$i]));
            }
             return 
    $Hex// String in hexadezimaler Schreibweise
     

    macht das.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Kein Wunder. Eine Hexzahl hat ja auch keine führenden Nullen. Genauso gut kannst Du eine 10, eine 8, eine 5 und eine 12 hinteiander kopieren und Dich über den selben Effkt wundern. Wenn Du eine Frage stellst, dannn sei bitte korrekt. Du benötigst einen 2-stelligen Hexcode. Also musst Du dem Programm das auch sagen. Das geht mannigfaltig bspw. über sprintf oder die Auswertung des jeweiligen Wertes.

    Einen Kommentar schreiben:


  • noch_anfaenger
    antwortet
    Zitat von lstegelitz Beitrag anzeigen

    Die Frage ist nun: Kennt die API deines I/O Gerätes eine Funktion, um ein komplettes WORD zu senden? Also eine Art Ersatz für SetValueBoolean()...
    Das ist noch nicht geklärt...
    Schon aber nächste Frage:
    Ich empfange Daten, die vom RFID-reader gesendet werden. Das Empfangen gelingt, das Auswerten macht aber Probleme. Daten werden als String empfangen. Um sie auszuwerten, muss ich sie in Hex konvertieren.
    Die Funktion
    PHP-Code:
     function stringToHex($string) {
       
    $hexstring='';
       for (
    $x=0;$x<strlen($string);$x++) {
            
    $hexstring.=dechex(ord(substr($string,$x,1)));
        }
        return(
    $hexstring);

    macht das, leider fehlerhaft: einige Nullen werden verloren.
    Statt "06 00 69 00 f6 fa" bekomme ich "60690f6fa". Die strlen($string)=6 wird aber richtig ausgerechnet, nach Anzahl der Blöcke.
    Hat vielleicht jemand eine Idee, wie man das richtig konvertieren kann?

    Einen Kommentar schreiben:


  • noch_anfaenger
    antwortet
    Sorry an mermshaus: ich bin nicht ganz oft in Foren, und manche Sachen wie "↓ Hm" sind mir unbekannt...

    Die Empfelungen werde ich nächste Woche ausprobieren.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Mein obiger Code sollte das übrigens schon können:

    $pinstatus = array_fill (0 , PORTS , false);
    $pinstatus[$port] = 'ON' == $value;
    Notfalls true/false durch 1/0 ersetzen und Array „implodieren“..

    Einen Kommentar schreiben:


  • lstegelitz
    antwortet
    Die Doku müsste dazu etwas sagen können.

    Ich kenn das so, das die einzelnen Pins eine Bitposition im Commandword haben.

    Um ein Bit an einer bestimmten Position zu setzen oder zu löschen verwendet man Bitoperationen:

    PHP-Code:
    // $cmdWord: bisheriges Commandword
    // $pos: Bitposition (0...31)
    // $clear: true/false (true: Bit soll gelöscht werden) 
    // Rückgabe: neues Commandword
    function setBit($cmdWord$pos$clear=false) {
      
    $bit << $pos;
      if (
    $clear$cmdWord $cmdWord & (~$bit); // bit löschen 
      
    else $cmdWord $cmdWord $bit// bit setzen

      
    return $cmdWord;

    Damit kann man nun beliebige Bitpositionen manipulieren:
    PHP-Code:
    $cmdWord 0// Alle Bitpositionen sind 0

    $cmdWord setBit($cmdWord0false); // Setze das 1. Bit 
    $cmdWord setBit($cmdWord5false); // Setze das 6. Bit 
    $cmdWord setBit($cmdWord8false); // Setze das 9. Bit 
    // nun weist $cmdWord diese Bitfolge auf (Big Endian)
    // 0000 0000 0000 0000 0000 0010 0100 0001

    $cmdWord setBit($cmdWord12false); // Setze das 13. Bit 
    $cmdWord setBit($cmdWord13false); // Setze das 14. Bit 
    $cmdWord setBit($cmdWord5true); // Lösche das 6. Bit wieder
    // 0000 0000 0000 0000 0110 0010 0000 0001 
    (Code ungetestet)

    Die Frage ist nun: Kennt die API deines I/O Gerätes eine Funktion, um ein komplettes WORD zu senden? Also eine Art Ersatz für SetValueBoolean()...

    Einen Kommentar schreiben:


  • mermshaus
    antwortet
    Offtopic:

    Zitat von noch_anfaenger Beitrag anzeigen
    Frage an mermshaus: was ist "↓ Hm, guter Punkt, "?
    Ein Kommentar zu lstegelitzens Beitrag eins drunter. Irgendwie verstehen wir uns nicht, habe ich das Gefühl. (Wie du die 12 Bits auf einmal schickst, dürfte übrigens auch am ehesten in der Doku des Geräts zu finden sein.)

    Einen Kommentar schreiben:


  • noch_anfaenger
    antwortet
    Zitat von lstegelitz Beitrag anzeigen
    ...SetValueBoolean. Vermutlich sendet die Funktion einen Wert an die angeschlossene Hardware.
    exakt!

    Zitat von lstegelitz Beitrag anzeigen
    Daher solltest du keine EINZELNEN Bits schicken, sondern immer ein komplettes Commandword zusammenbauen (12 bit bei dir) und das senden, also 12 Operationen zusammen - falls das überhaupt machbar ist.
    Wie kann man das machen?

    Zitat von lstegelitz Beitrag anzeigen
    Was sagt denn die Doku zu dem Gerät, wie schnell die Übertragungsrate ist (kann eventuell ja auch konfiguriert und erhöht werden?)
    Diese Frage kann ich jetzt nicht beantworten. Das ist aber ein sehr guter Hinweis!

    PS. PHP ist eine Bedingung, die ich nicht ändern darf.

    Frage an mermshaus: was ist "↓ Hm, guter Punkt, "?

    Einen Kommentar schreiben:


  • lstegelitz
    antwortet
    Zitat von noch_anfaenger Beitrag anzeigen
    Ich muss true oder false an bestimmte IDs für INPUT und OUTPUT setzen.
    PHP-Code:
    switch ($key) {   // Key steht hier für port_out
                     
    case "0":
                    
    SetValueBoolean($id_0true);
                    break;
                    case 
    "1":
                    
    SetValueBoolean($id_1true);
                    break;... 
    Und das dauert lange.
    Du hast deinen Flaschenhals bereits erkannt - es ist aber nicht das switch-statement, sondern SetValueBoolean. Vermutlich sendet die Funktion einen Wert an die angeschlossene Hardware.

    Bei INP und OUTP muss ich immer an die Kommunikation mit der seriellen Schnittstelle unter MS-DOS denken. Die Übertragungsraten von dem Ding waren grauenhaft... tippe darauf, das sich das in diesem Fall ähnlich verhält.
    Daher solltest du keine EINZELNEN Bits schicken, sondern immer ein komplettes Commandword zusammenbauen (12 bit bei dir) und das senden, also 12 Operationen zusammen - falls das überhaupt machbar ist.

    Was sagt denn die Doku zu dem Gerät, wie schnell die Übertragungsrate ist (kann eventuell ja auch konfiguriert und erhöht werden?)

    Einen Kommentar schreiben:


  • mermshaus
    antwortet
    Na ja, du sagtest, die Switch-Konstrukte seien zu langsam. Ich fragte mehr oder weniger interessehalber, woran du das festmachst. Ich hätte spontan getippt, array_reverse oder base_convert oder substr seien langsamer. Aber das wäre geraten gewesen.

    Wahrscheinlich liegt die größte Geschwindigkeitsbremse ohnehin nicht im Code selbst, sondern im Initialisieren von PHP. Dazu wird dir sicher noch jemand eine kompetentere Antwort geben können.

    Wie macht sich denn bemerkbar, dass das Script zu wenig performant ist? Vielleicht ist PHP die falsche Sprache.

    Edit: ↓ Hm, guter Punkt, schätze ich.

    Einen Kommentar schreiben:


  • noch_anfaenger
    antwortet
    Vielleciht habe ich nicht richtig erklärt, was ich brauche. Ich brauche nicht das schöne Aussehen von meinem Code, sondern seine Schnelligkeit. Wenn ich jetzt den Beitrag von mermshaus lese, verstehe ich nur Bahnhof. Welche Funktionen sind gemeint?

    Einen Kommentar schreiben:


  • mermshaus
    antwortet
    Zitat von noch_anfaenger
    aber nicht ganz schnell, da es viele switch statements gibt
    Und das dauert lange.
    Mich würde mal interessieren, woran du das festmachst. Wenn ich das langsamste Stück Code nennen sollte, hätte ich vermutlich auf eine der Funktionen getippt.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Ja und? nimmste halt $pinstatus[$port].

    Hier wird der sog. 'ternäre' Operator ? : implizit verwendet.
    Nicht wirklich. Dort wird nur das Ergebnis eines boolschen Vergleichs zugewiesen.

    Einen Kommentar schreiben:


  • noch_anfaenger
    antwortet
    Ich muss true oder false an bestimmte IDs für INPUT und OUTPUT setzen.
    PHP-Code:
    switch ($key) {   // Key steht hier für port_out
                     
    case "0":
                    
    SetValueBoolean($id_0true);
                    break;
                    case 
    "1":
                    
    SetValueBoolean($id_1true);
                    break;... 
    Und das dauert lange.

    Einen Kommentar schreiben:

Lädt...
X