Ankündigung

Einklappen
Keine Ankündigung bisher.

Counterskript - Ressourcenverbrauch? Optimierbar?

Einklappen

Neue Werbung 2019

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

  • Counterskript - Ressourcenverbrauch? Optimierbar?

    Hallo zusammen,

    ich hab folgendes Counter-Skript programmiert, das (wie ihr seht) den Counterstand aus der DB ausliest und dann in eine Grafik umsetzt.
    Da das Skript im Rahmen eines Counterservices laufen soll, muss es natürlich soweit wie möglich ressourcenschonend sein.
    Leider kann ich das selbst nicht beurteilen.
    Kann mir jemand von euch zum Ressourcenverbrauch dieser Zeilen etwas sagen bzw., was man besser machen könnte?

    PHP-Code:
    $benutzername $_GET['benutzername'];
    session_start();
    if (!isset(
    $_SESSION['gezaehlt'])) 
    {
        
    // Besucher wurde noch nicht gezählt => Counter++
        
    $timestamp time();
        
    $aufrufurl $_SERVER["HTTP_REFERER"];
        
    $sql "UPDATE USERTAB SET Counterstand = Counterstand+1, Aufrufurl = '$aufrufurl', ";
    $sql .= "Letzteraufruf = '$timestamp' WHERE Benutzername = '$benutzername'";
        
    mysql_query($sql);
        
    // Session auf gezaehlt setzen
        
    $_SESSION["gezaehlt"] = true;
    }
    // Counterstand anzeigen
    $sql "SELECT * FROM USERTAB WHERE Benutzername = '$benutzername'";
    if (
    $res mysql_query($sql))
    {
        while(
    $data mysql_fetch_array($res))
        {
            
    $counterstand $data["Counterstand"];
            
    $counterlaenge $data["Counterlaenge"];
            
    $counterbild $data["Counterbild"];
        }
        
    $laenge_akt strlen($counterstand);
        
    // Nullen anhängen, damit der Counter die richtige Länge hat
        
    for ($n=1$n<=$counterlaenge-$laenge_akt;$n++)
        {
            
    $counterstand "0".$counterstand;
        }
        
    // Counterbild generieren
        
    $masse GetImageSize("http://www.meinedomain.de/digits/$counterbild/1.gif");
        
    $breite $masse[0];
        
    $hoehe $masse[1];
        
    $gesamtbreite $breite*$counterlaenge;
        
    $counter ImageCreateTrueColor($gesamtbreite,$hoehe);
        for (
    $n=1$n<=$counterlaenge$n++)
        {
            
    $ziffer[$n] = substr ($counterstand$n-11);
            
    $bild[$n] = ImageCreateFromGif("http://www.meinedomain.de/digits/$counterbild/$ziffer[$n].gif");
            
    imagecopymerge ($counter$bild[$n], $xpos000$breite$hoehe100);
            
    $xpos $xpos $breite;
        }
    }
    Header("Content-type: image/gif");
    ImageGIF($counter);
    ImageDestroy($counter); 
    Danke und viele Grüße,

    Kai


  • #2
    Hallo Kai.

    Ein paar Anmerkungen:

    1. Kannst du sicherstellen, dass auf dem Server immer magic_quotes_gpc an ist? Andernfalls kann man ja ganz leicht z.B. alle Counter pro durchlauf hochzählen lassen.

    2. Bist du sicher, dass $_SERVER["HTTP_REFERER"] nicht mit Steuerzeichen bestückt werden kann? Müsstest du mal ausprobieren, falls nicht.

    3. Anstatt SELECT * nur die Felder auslesen, de du tatsächlich brachst und Indizes verwenden.

    4. Anstatt mysql_fetch_array() entweder mysql_fetch_assoc() oder mysql_fetch_row() verwenden.

    5. Ist mysqli schneller? Könnte sein, weiß nicht...

    6. Für deine Nullen gibt es str_pad().

    7. Für die Ziffernmaße ist es vielleicht schonender, diese in eine Info-Datei in das $counter-Bild verzeichnis zu legen. Musst du mal ausprobieren, welche Methode da am schnellsten ist.

    8. Die Bilder über HTP ins Skript zu halten ist natürlich Käse!

    9. Ich denke mal, du fährst am besten, wenn du die Bilder cachest.

    10. Anstatt substr(...) kannst du auch $counterstand{$n} schreiben.

    11. Pack die einzelnen Bilder nicht in ein Array, sondern in eine einfache Variable, die du dann jeweils wieder überschreibst beim nächsten Durchlauf. Macht ja keinen Sinn, die zu speichern.

    12. Gib doch zuerst das Bild aus und dann aktualisiere die Datenbank.

    Keine Ahnung, ob diese Verbesserungen auch nur annähernd relevant sein könnten...

    Mir kommt grad die Idee, einfach pro Kunden eine SymLink auf die jeweils nächste, schon zusammengesetzt Ziffer zu sezten. Im Skript gibst du einfach das Bild aus (ganz ohne die gd2-Funktionen) und setzt dann den Link eins weiter, wobei du vorher ggf. die neue Zahl generierst. Wäre sicherlich eine feine Sache, allerdings weiß ich nicht, wie man das Linkziel nur mit PHP herausbekommt.

    Nochwas:
    Die Session-Lösung ist ziemlich dürftig. Einfach einen Cookie zu setzen ist schneller und hat den gleichen Effekt. Andernfalls müsstest du zumindest probieren, den Benutzer irgendwie wiederzuerkennen.

    Basti

    Kommentar


    • #3
      Auch noch eine Anmerkung von mir:
      Zitat von Basti
      6. Für deine Nullen gibt es str_pad().
      Hier würde ich mit dem Attribut MySQL-Spaltenattribut ZEROFILL arbeiten. Dann übernimmt MySQL das auffüllen der Zahl mit 0 selbst.

      Kommentar


      • #4
        Und beim Auswählen des Benutzers per "SELECT * FROM USERTAB WHERE
        Benutzername = '$benutzername'" könntest du LIMIT 1 verwenden, denn es
        gibt ja nur einen Benutzer (oder etwa nicht?). Das erspart MySQL die Suche
        nach weiteren $benutzername'n und ist dadurch erheblich schneller.
        Außerdem ist die while-Schleife überflüßig.

        Ich weiß nich wie deine GIFs aussehen, aber vielleicht kannst du diese ja
        durch CSS ersetzen?
        PHP-Code:
        <?php
        printf
        ('<span style="height:%upx;width:%upx;background-color:%s;border:1px outset %s"></span>'$hoehe$breite'silver''green');
        ?>

        Kommentar


        • #5
          Vielen Dank für eure ausführlichen Anworten!! Zu einige genannten Punkten muss ich allerdings erstmal ein bisschen recherchieren, weil ich deren Sinn nicht auf Anhieb verstehe. Melde mich dann wieder, wenn ich schlauer geworden bin...

          Viele Grüße,

          Kai

          Kommentar


          • #6
            @ Basti

            Die meisten Punkte sind klar, bei folgenden weiß ich nicht genau, was du meinst:

            Zu 8: Welche Alternative gibt es dazu und was ist deren Vorteil?
            Zu 9: Könntest du kurz genauer erklären, wie du das meinst?

            Vielen Dank und viele Grüße,

            Kai

            Kommentar


            • #7
              Hallo Kai

              Zitat von Kaischum
              [Bilder über HTTP laden]

              Welche Alternative gibt es dazu und was ist deren Vorteil?
              Du wirst die Bilder doch auf deinem Server liegen haben. Also kannst du
              sie doch einfach über den Dateipfad ansprechen. Es ist ziemlich
              übertrieben, für jede Ziffer eines Counters bei jedem(!) Aufruf eine
              Anfragedurchs Netz zu jagen. Selbst wenn die Ziffern beim Kunden liegen,
              dann reichen zehn Anfragen, um die zehn Ziffern auf deinen Server zu
              holen und wenn der Kunde was ändert, soll er halt mit einem Klick
              irgendwo eine Aktualisierung deiner Ziffern veranlassen.

              [Cacheing]

              Zu 9: Könntest du kurz genauer erklären, wie du das meinst?
              Es ist doch anzunehmen, dass mehrere Kunden die selben Ziffern und die
              selbe Counterlänge verwenden, oder? In dem Fall wäre es doch unnötig,
              die Bilder jedes mal neu zusammenzustellen. Leg dir die berechneten
              Bilder einfach mit dem Namen der Zahl in den Ordner des Themes und
              schau bei den Aufrufen, ob das entsprechende Bild bereits existiert und
              erzeuge es nur dann, wenn es eben noch nicht existiert.

              Möglich wäre auch, wirklich viele von diesen Bildern im Voraus zu
              berechnen und auf den Server zu legen und dann per Cron-Job zu
              überwachen. Ist halt dann die Frage, wie schnell die Platte die Daten
              ausliefern kann, wenn du ein paar Hunderttausend 1kB-Bildchen drauf
              liegen hast.

              Ich denke, es gibt unzählige Möglichkeiten, das anzugehen. Eine wäreauch
              z.B. folgende:
              PHP-Code:
              <?php

              // get user data
              $iUser = (int) $_GET['user'];
              $sHits file_get_contents("../stats/$iUser"); // i.e. 12456
              list($sTheme$sLen) = explode("\t"file_get_contents("../users/$iUser")); // back_and_white    6

              // echo image
              header("Content-type: image/gif");
              echo 
              file_get_contents("../cache/$sTheme/$sLen/$sHits");
              flush();

              // increase counter
              $iHits = (int) $sHits;
              $iHits++;

              // don't point on not existing files
              if (!file_exists("../cache/$sTheme/$sLen/$iHits")) admin_notification();

              // write new counter value to users stat file
              file_put_contents("../stats/$iUser"$iHits);

              // create some new images on buffer underrun
              if (!file_exist("../cache/$sTheme/$sLen/" settype($iHits 50'string')))
                  
              create_next_100_pic(...);
              ?>
              Da gibt es natürlich eine Race Condition, aber in dem Umfang in dem du
              das betreibst (unterstelle ich mal) und angesichts des minimalen
              Schadens, wenn mal ein Besucher verschluckt wird bzw. angesichts der
              Ungenauigkeit durch die Session-Funktion (die hier grad nicht drinnen ist)
              und der Manipulierbarkeit ist das eh Wurscht.

              Basti

              Kommentar

              Lädt...
              X