Andy: Zufallsystem - Wieso microtime?

Hallo,

wieso immer microtime?

ich mach das immer so:

funktion zufall(){
$id = rand($min,$max);

und eine abfrage in der datenbank, ob die id schon vorhanden ist

  • wenn ja function wiederholen (solange bis er eine freie id hat)
  • wenn nein und id frei, id in db eintragen
    }

was spricht dagegen?

  1. Hi,

    wieso immer microtime?

    weil das pro einzelnem Scriptaufruf relativ zufällig ist.

    ich mach das immer so:

    [...]

    Jiargl.

    was spricht dagegen?

    So ziemlich alles, begonnen bei der Vernunft. Dein Algorithmus terminiert nicht, und er ist *extrem* zeit- und performancelastig.

    Cheatah

    --
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo,

      ich zitiere mal aus dem Manual:

      "Benutzen Sie unbedingt srand(), um vor dem ersten Aufruf von rand() einen neuen Startwert festzulegen, ansonsten erhalten Sie bei jedem Programmlauf dieselbe Sequenz von Werten."

      Auch das würde mich schon stören.

      Ich weiß nicht, wie PHP das macht, aber bei Pascal hat die Random-Funktion einfach nur nach einem speziellen Alogithmus den Speicher durchgelesen und Werte gegeneinander verrechnet. Wenn dann zwischendurch keine Speichernutzung (in dem Bereich) stattgefunden hatte, bekam man tatsächlich dutzende Male nacheinander den selben Wert.

      Grüße

      Tom

      1. hi,

        Ich weiß nicht, wie PHP das macht, aber bei Pascal hat die Random-Funktion einfach nur nach einem speziellen Alogithmus den Speicher durchgelesen und Werte gegeneinander verrechnet. Wenn dann zwischendurch keine Speichernutzung (in dem Bereich) stattgefunden hatte, bekam man tatsächlich dutzende Male nacheinander den selben Wert.

        und so oder ähnlich wird es in jeder anderen programmiersprache auch gehandhabt - ganz einfach deshalb, weil ein "echter" zufall sich nicht mathematisch berechnen lässt.

        ergo sollte man einen veränderlichen startwert verwenden.
        die aktuelle zeit ist dafür ganz gut geeignet.
        wenn man den tag als initialisierungswert verwendet, bekäme man einen ganzen tag lang immer die selbe abfolge. also verwendet man eine kleinere unterteilung der zeit - microtime bietet sich deshalb an.

        gruss,
        wahsaga

      2. Hallo!

        ich zitiere mal aus dem Manual:

        "Benutzen Sie unbedingt srand(), um vor dem ersten Aufruf von rand() einen neuen Startwert festzulegen, ansonsten erhalten Sie bei jedem Programmlauf dieselbe Sequenz von Werten."

        und ich zitiere weiter:

        "Anmerkung:  Seit PHP 4.2.0 ist es nicht mehr nötig, den Zufallszahlengenerator zu initialisieren, bevor man ihn benutzt."
        Quelle: http://de3.php.net/manual/de/function.rand.php

        und noch weiter:

        "Die PHP rand() Funktion benutzt den in der jeweiligen libc enthaltenen Zufallsgenerator. Gerade in älteren libc-Versionen ist dieser aber oft langsam und die Qualität der erzeugten Pseudozufalls-Sequenzen ist unbefriedigend bis unbekannt.

        Die Funktion mt_rand() bietet einen Drop-In Ersatz für die von der libc bereitgestellten Funktionen. Sie benutzt einen Zufallsgenerator mit bekannter Characteristik, den sogenannten "Mersenne Twister", der Pseudozufalls-Sequenzen generiert, die auch kryptografischen Ansprüchen genügen sollten und viermal so schnell arbeitet wie der typische libc-Algorithmus. "
        Quelle: http://de3.php.net/manual/de/function.mt-rand.php

        Ich weiß nicht, wie PHP das macht, aber bei Pascal hat die Random-Funktion einfach nur nach einem speziellen Alogithmus den Speicher durchgelesen und Werte gegeneinander verrechnet. Wenn dann zwischendurch keine Speichernutzung (in dem Bereich) stattgefunden hatte, bekam man tatsächlich dutzende Male nacheinander den selben Wert.

        siehe Zitat/Link.
        Das schlimme an der bisherigen Variante(sollte PHP < 4.2 eingesetzt worden sein), dann wiederholt sich die Sequenz der Zufallszahlen bei jedem Scriptaufruf, das heißt dass nur der erste Eintrag sofort gemacht wird, beim nächsten wird wieder die 1. Zahl probiert, die es dann aber gibt, und dann funktioniert die 2. Bei der 3. Zahl werden wieder die ersten beiden probiert, erst beim 3. Versuch wirds klappen. Und dasselbe beim 100., 1000., ... wie man sieht, extrem ineffizient.

        Naja, mit neueren PHP-Versionen(>= 4.2) ist das wohl automatisiert worden - warum auch nicht, vermutlich haben es eh (fast ;-)) alle so gemacht wie im Manual-Beispiel.

        Grüße
        Andreas

        1. Hi,

          ich zitiere mal aus dem Manual:

          [...]

          "Die PHP rand() Funktion benutzt den in der jeweiligen libc enthaltenen Zufallsgenerator. Gerade in älteren libc-Versionen ist dieser aber oft langsam und die Qualität der erzeugten Pseudozufalls-Sequenzen ist unbefriedigend bis unbekannt.

          Diese Vorgehensweise vestehe ich bis heute nicht. Wenn das Manual den tatäschlichen Code wirklich wiederspiegelt (ich habe ihn leider nicht auf Platte und bin zu faul, mir das Paket einzuspielen) ist diese Vorgehensweise zu mißbilligen. Entweder holt man sich die Zufallszahlen aus dem OS (/dev/random o.ä. bei Unices) oder, wenn nicht vorhanden oder zu schlecht, implementiert man sich das selber. Wir haben 2003, es gibt sehr viele Algorithmen, die das gut und schnell und vor allem kryptograhisch ausreichend machen können (Der "Mersenne Twister" ist hier kein gutes Beipiel).

          Die funktion rand() ist in den aktuellen GLibcs gut dokumentiert, vielleicht lohnt sich einmal reinschauen? $GLIBC_SRC_ROOT/stdlib/random.c (hier glibc-2.3.2)
          Und als Gegensatz dazu die rand() Funktion von OpenSLL $OPENSSL_SRC_ROOT/crypto/rand/md_rand.c.
          Auch die rand() Funtkionen von FreeBSD sind gut kommentiert BSD/lib/libc/stdlib/rand.c

          Naja, mit neueren PHP-Versionen(>= 4.2) ist das wohl automatisiert worden - warum auch nicht, vermutlich haben es eh (fast ;-)) alle so gemacht wie im Manual-Beispiel.

          So richtig ordentlich ist das auch nicht, da man auch hier normalerweise ein Stück der erzeugten Zufallszahl als Seed behalten und vor allem nutzen sollte.
          Für normale Ansprüche reicht es, Verschlüsselung würde ich damit aber nicht betreiben wollen.

          so short

          Christoph Zurnieden

  2. <?php
    SESSION_START();
    SESSION_REGISTER("lids");

    print "LIDS: $lids<br>";

    $max = '5';

    zufall();
    function zufall ()
    {
     global $max, $id, $lids, $lid;

    mt_srand ((double)microtime()*1000000);
     $id = mt_rand(0,$max);

    $exp_lids = explode("|", $lids);
     $count = count($exp_lids)-1;
     for ($i=0; $i <= $count; $i++)
     {
      $lid = $exp_lids[$i];
      if ($lid == $id) zufall();
     }
    }

    $lids = $id."|".$lids;

    print "ID: $id<br>";
    ?>

    ist das nicht die perfekte lösung?

    1. Hi,

      ist das nicht die perfekte lösung?

      ja, es ist nicht die perfekte Lösung. Warum fragst Du?

      Cheatah

      --
      X-Will-Answer-Email: No
      X-Please-Search-Archive-First: Absolutely Yes
      1. ja, es ist nicht die perfekte Lösung. Warum fragst Du?

        du bist ja ne tolle hilfe.

        1. Hi,

          ja, es ist nicht die perfekte Lösung. Warum fragst Du?
          du bist ja ne tolle hilfe.

          danke, gern geschehen. Was hättest Du denn ob Deiner Frage erwartet? Dass ich Dir auf die Schulter klopfe?

          Cheatah

          --
          X-Will-Answer-Email: No
          X-Please-Search-Archive-First: Absolutely Yes
    2. Huhu Andy

      ist das nicht die perfekte lösung?

      es mag funktionieren, aber perfekt würde ich es nicht nennen

      <?php
      SESSION_START();
      SESSION_REGISTER("lids");

      benutze besser das "super global"- Array $_SESSION

      print "LIDS: $lids<br>";

      $max = '5';

      Du möchtest einen Zahl (Integer) und keinen String oder?

      zufall();

      Funktionsaufruf steht vor der Funktionsdefinition, das funktioniert
      zwar, empfinde ich persönlich aber als schlechten Stil.

      function zufall ()

      schlecht gewählter Funktionsname

      {
      global $max, $id, $lids, $lid;

      global ist meistens unnötig und ist im Hinblick auf vernünftige
      Modularisierung kontraproduktiv.

      mt_srand ((double)microtime()*1000000);

      das musst Du nur einmal im Skript aufrufen

      $id = mt_rand(0,$max);

      $exp_lids = explode("|", $lids);
      $count = count($exp_lids)-1;
      for ($i=0; $i <= $count; $i++)
      {
        $lid = $exp_lids[$i];
        if ($lid == $id) zufall();

      hier gefährlicher rekursiver Aufruf, da eine Endlos-Schleife
      sehr leicht möglich ist.

      }

      Deine Funktion hat keinen Rückgabewert

      }

      $lids = $id."|".$lids;

      print "ID: $id<br>";
      ?>

      Also nochmal von vorne ...

      Viele Grüße

      lulu

      --
      bythewaythewebsuxgoofflineandenjoytheday
      1. Huhu Andy

        ist das nicht die perfekte lösung?

        es mag funktionieren, aber perfekt würde ich es nicht nennen

        wenn es doch gut funktioniert warum nicht anwenden???

        SESSION_REGISTER("lids");
        benutze besser das "super global"- Array $_SESSION

        Kenne ich nicht - kannst du mir das mal genaue erklären?

        $max = '5';
        Du möchtest einen Zahl (Integer) und keinen String oder?

        $max = 5; ist doch eh nur n test später kommt die zuweisung aus der db

        zufall();
        Funktionsaufruf steht vor der Funktionsdefinition, das funktioniert zwar, empfinde ich persönlich aber als schlechten Stil.

        ja ok

        function zufall ()
        schlecht gewählter Funktionsname

        ist doch scheiss egal!

        {
        global $max, $id, $lids, $lid;
        global ist meistens unnötig und ist im Hinblick auf vernünftige
        Modularisierung kontraproduktiv.

        wie kann ich es denn asutrixen? wenn ich es weglasse geht nix, dann müsste ich den funktionsaufruf anders gestalten.

        if ($lid == $id) zufall();
        hier gefährlicher rekursiver Aufruf, da eine Endlos-Schleife
        sehr leicht möglich ist.

        äh? ne

        Deine Funktion hat keinen Rückgabewert

        jetzt schon, aber ich häng noch an den oberen probs

        Viele Grüße

        lulu

        Danke

        1. Hi,

          wenn es doch gut funktioniert warum nicht anwenden???

          dieses sogenannte Argument ist das vermutlich gefährlichste überhaupt. Seine Benutzung ist in aller Regel ein klares Indiz dafür, dass die betreffende Verfahrensweise unter gar keinen Umständen benutzt werden sollte.

          schlecht gewählter Funktionsname
          ist doch scheiss egal!

          Nein, nicht im mindesten.

          global $max, $id, $lids, $lid;
          global ist meistens unnötig und ist im Hinblick auf vernünftige
          Modularisierung kontraproduktiv.
          wie kann ich es denn asutrixen?

          Nicht "austricksen", sondern richtig machen. Zu verwendende Variablen und Werte über- und zurückgeben.

          if ($lid == $id) zufall();
          hier gefährlicher rekursiver Aufruf, da eine Endlos-Schleife
          sehr leicht möglich ist.
          äh? ne

          Äh, doch.

          Cheatah

          --
          X-Will-Answer-Email: No
          X-Please-Search-Archive-First: Absolutely Yes
        2. Huhu Andy

          wenn es doch gut funktioniert warum nicht anwenden???

          Du hast gefragt ob es perfekt ist, Du kannst es selbstverständlich benutzen, ist ja Dein Programm ;-)

          SESSION_REGISTER("lids");
          benutze besser das "super global"- Array $_SESSION
          Kenne ich nicht - kannst du mir das mal genaue erklären?

          ist eigentlich ganz einfach, Du brauchst dem $_SESSION-Array nur etwas
          zuweisen und - schwubs - ist es automatisch in der Session registriert.
          Beispiel:

          $_SESSION['SomeKey'] = 'WhatEver';
          Macht die Sache schön einfach.
          Details findest Du im Manual

          $max = '5';
          Du möchtest einen Zahl (Integer) und keinen String oder?
          $max = 5; ist doch eh nur n test später kommt die zuweisung aus der db

          Was spricht dagegen es gleich richtig zu machen?

          function zufall ()
          schlecht gewählter Funktionsname
          ist doch scheiss egal!

          Nein, ist es ganz sicher nicht.
          In diesem Fall finde ich den Namen als solches nicht schlecht, allerdings passt er nicht zu dem was die Funktion tut.

          Ich überlege oft länger welchen Namen ich für eine Funktion vergebe als ich zum Schreiben der Funktion brauche.
          Bei grösseren Projekten wirst Du sonst wahnsinnig wenn die Funktionsnamen schlecht gewählt sind, weil Du immer nachgucken musst was sie eigentlich tut.

          Bei einer Funktion zufall() würde ich erwarten, dass sie mir eine
          Zufallszahl als Rückgabewert liefert, wobei ich den Wertebereiche durch (optionale)
          Parameter vorgeben kann.

          global ist meistens unnötig
          wie kann ich es denn asutrixen? wenn ich es weglasse geht nix, dann müsste ich den funktionsaufruf anders gestalten.

          Genau so.

          if ($lid == $id) zufall();
          hier gefährlicher rekursiver Aufruf, da eine Endlos-Schleife
          sehr leicht möglich ist.
          äh? ne

          hier mal in wörtlicher Rede beschrieben was Dein Skript tut:

          ermittele eine Zufallszahl zwischen 0 und 5
          gehe eine vorhanden Liste von Zahlen der Reihe nach durch
          wenn ein Element der Liste der gezogenen Zufallszahl entspricht beginne von vorne

          Jetzt stell Dir mal als Ausgangssituation folgende Liste vor:

          0,1,2,3,4,5

          Preisfrage wie lange läuft das Skript auf, sagen wir mal
          einem pIII mit 1,4 GHz und 256 MB Ram ?

          Ach ja das Gehäuse ist wallnussfarben ...

          Viele Grüße

          lulu

          --
          bythewaythewebsuxgoofflineandenjoytheday
          1. global ist meistens unnötig
            wie kann ich es denn asutrixen? wenn ich es weglasse geht nix, dann müsste ich den funktionsaufruf anders gestalten.

            Genau so.

            äh... ja...

            aufruf schön und gut aber wie bekomme ich die variablen aus der funktion, im prinzip hätte ich es gern so, dass die ganze funktion so arbeiten würde als ob sie garkeine wäre und alle variblen global wären - gibt es nicht sowas wie global_all oder so?

            MfG Andy

            1. Hi Andy,

              aufruf schön und gut aber wie bekomme ich die variablen aus der funktion, im prinzip hätte ich es gern so, dass die ganze funktion so arbeiten würde als ob sie garkeine wäre und alle variblen global wären - gibt es nicht sowas wie global_all oder so?

              Hatten wir das nicht schon? :-) Könnte aber auch ein anderer Thread gewesen sein *grins*

              $ergebnis = functionVon($argument);

              Das wäre ein "normaler" Funktionsaufruf. Jede Funktion liefert genau einen Rückgabewert.

              PHP kann mehr:

              $ergebnisArray = function($argument1, $argument2, $inputArray);

              Jede Hochsprache kann auch noch den "Call By Reference":

              $daten = [typ];  ### Allokation von Speicher

              $ergebnis = function(&$daten);

              Das Kaufmannsund vor dem Argument besagt nun, dass nicht eine Kopie von $daten an die Funktion zur freien Verwendung übergeben wird, sondern die Adresse von $daten im Speicher. Darum mussten wir auch vorher Speicherplatz dafür anlegen (allokieren).

              Nun kann die Funktion mit $daten nicht mehr machen, was sie will, sondern muss aufpassen, was sie intern damit veranstaltet. Das externe $daten und das funktionsinterne sind nämlich nun identisch. Es gibt also nur noch ein $daten. Das ist fast so, wie GLOBAL, nur dass man den Übergabe-Parameter noch freie wählen kann. Bei GLOBAL ist der ja fest verdrahtet in der Funktion. Funktionen mit GLOBAL haben daher Reentranzprobleme. Man darf sie nich ohne weiteres rekursiv verwenden. VAR (Variable Access Reference) oder "Call by Reference" - Aufrufe sind da schon vorteilhafter.

              Ich habe mit inzwischen die Variante mit dem Rückgabearray angewöhnt, wenn genügend Speicher zur Verfügung steht.
              Ein VAR-Aufruf benötigt nämlich ggf. weniger Arbeitsspeicher, weil die Variable nicht vor Funktionsaufruf kopiert werden muss.

              Ich hoffe, nun hast Du einige Anregungen bekommen.

              Grüße

              Tom

              1. das ist ja einiges ;-)

                [pref:t=61863&m=349415]

                ich hab leider nicht ganz verstanden was das mit diesem speicher auf sich hat, das geht mir schon zu sehr in richtung c++.

                aber es hat sich so nach GLOBAL ALL angehört, kannst nicht mal mein script auf deine art und weise anpasen?

                MfG Andy

        3. Hi,

          ist das nicht die perfekte lösung?

          es mag funktionieren, aber perfekt würde ich es nicht nennen
          wenn es doch gut funktioniert warum nicht anwenden???

          Wenn es funktioniert, ist das ein Indiz dafür, da Du nicht richtig getestet hast. Siehe auch Antwort von Lulu.
          Merke Dir bitte: Man testet Software nicht auf Funktion sondern auf Fehler!

          $max = '5';
          Du möchtest einen Zahl (Integer) und keinen String oder?
          $max = 5; ist doch eh nur n test später kommt die zuweisung aus der db

          Ein Grund mehr, die Richtigkeit aller externen Variablen zu prüfen. (Größe und in Deinem Fall noch Typ).

          zufall();
          Funktionsaufruf steht vor der Funktionsdefinition, das funktioniert zwar, empfinde ich persönlich aber als schlechten Stil.
          ja ok

          Einfaches Beispiel warum das unter anderem schlecht ist: das Script wird von Anfang zum Ende geparst. Wenn nun die Benutzung vor der Defnition kommt, muß doppelte Arbeit geleistet werden.

          function zufall ()
          schlecht gewählter Funktionsname
          ist doch scheiss egal!

          Gut gewählte Funktionsnamen erleichtern spätere Arbeit ungemein. Glaub's uns, wir haben auch aus unseren Fehlern lernen müssen ;-)

          {
          global $max, $id, $lids, $lid;
          global ist meistens unnötig und ist im Hinblick auf vernünftige
          Modularisierung kontraproduktiv.
          wie kann ich es denn asutrixen? wenn ich es weglasse geht nix, dann müsste ich den funktionsaufruf anders gestalten.

          Dann mußt Du den Funktionsaufruf eben anders gestalten. Noch ein Problem damit: hier "if ($lid == $id) zufall();" ist ein rekursiver Aufruf. Wegen der globalen Variablen ist diese Funktion aber nicht reentrant. Das funktoniert bei PHP weil dort "global" keine wirklich globalen Variablen erzeugt, aber mach es trotzdem nicht, das geht meist in's Auge.

          Deine Funktion hat keinen Rückgabewert
          jetzt schon, aber ich häng noch an den oberen probs

          Warum nimmst Du eigentlich nicht die von PHP angebotenen hauseigenen SessionIDs? Oder eine MD5Sum über Microtime? Alles deutlich einfacher und sicherer.

          so short

          Christoph Zurnieden

          1. Hallo,

            Einfaches Beispiel warum das unter anderem schlecht ist: das Script wird von Anfang zum Ende geparst. Wenn nun die Benutzung vor der Defnition kommt, muß doppelte Arbeit geleistet werden.

            Da bin ich skeptisch. PHP arbeitet mit einem Dual Pass Parser. Das bedeutet, dass beim ersten Durchlauf sämtliche Bezeichner eingesmmelt werden und erst beim zweiten Durchlauf die Ausführung gestartet wird.

            Schlechter Stil ist es trotzdem. Ein Programm sollte so leicht lesbar sein, wie ein Buch, von vorne nach hinten. Abweichungen hiervon gebühren der ordentlichen Dokumentation an geeigneter Stelle.

            Grüße

            Tom

            1. Hi,

              Einfaches Beispiel warum das unter anderem schlecht ist: das Script wird von Anfang zum Ende geparst. Wenn nun die Benutzung vor der Defnition kommt, muß doppelte Arbeit geleistet werden.

              Da bin ich skeptisch. PHP arbeitet mit einem Dual Pass Parser. Das bedeutet, dass beim ersten Durchlauf sämtliche Bezeichner eingesmmelt werden und erst beim zweiten Durchlauf die Ausführung gestartet wird.

              Da ich leider die Quellen nicht zur Hand habe, bin ich jetzt nur auf Hörensagen angewiesen, also folgendes mit Vorbehalt:
              Wenn der PHGP-Parser beim erstem Durchlauf alles drin hat, wird der zweite Durchlauf gar nicht erst gestartet. Da PHP aber optimiert, dürfte dieser Fall recht selten eintreten, zugegeben.

              Schlechter Stil ist es trotzdem. Ein Programm sollte so leicht lesbar sein, wie ein Buch, von vorne nach hinten.

              Naja, das läßt sich nicht immer so machen, aber dann auch ...

              Abweichungen hiervon gebühren der ordentlichen Dokumentation an geeigneter Stelle.

              Genau! ;-)

              so short

              Christoph Zurneiden

              1. Hallo Christoph,

                Da ich leider die Quellen nicht zur Hand habe, bin ich jetzt nur auf Hörensagen angewiesen, also folgendes mit Vorbehalt:
                Wenn der PHGP-Parser beim erstem Durchlauf alles drin hat, wird der zweite Durchlauf gar nicht erst gestartet. Da PHP aber optimiert, dürfte dieser Fall recht selten eintreten, zugegeben.

                Das würde mich dann doch noch mal genauer interessieren. Ich ahbe inzwischen ziemliche Monsterscripte geschrieben (mehrere 100K groß) und die sond teilweise trotzdem noch schnell. Vielleicht kann ich an den Bummelanten dann noch was verbessern (kann man ja eigentlich immer).

                Grüße

                Tom

                1. Hallo Christoph,

                  Da ich leider die Quellen nicht zur Hand habe, bin ich jetzt nur auf Hörensagen angewiesen, also folgendes mit Vorbehalt:
                  Wenn der PHGP-Parser beim erstem Durchlauf alles drin hat, wird der zweite Durchlauf gar nicht erst gestartet. Da PHP aber optimiert, dürfte dieser Fall recht selten eintreten, zugegeben.

                  Das würde mich dann doch noch mal genauer interessieren. Ich ahbe inzwischen ziemliche Monsterscripte geschrieben (mehrere 100K groß) und die sond teilweise trotzdem noch schnell. Vielleicht kann ich an den Bummelanten dann noch was verbessern (kann man ja eigentlich immer).

                  Normalerweise ist der Zend-Optimierer in den meisten Fällen mit drin, wenn nicht: einbauen. (Falls Dir die Lizenz zusagt natürlich). Das reicht meist schon.

                  Aber prinzipiell: wenn die Geschwindigkeit ausreicht - also keine Anfrage weggeschmissen wird, weil der Prozessor am Anschlag arbeitet oder kein Speicher mehr frei ist, oder gar andere Programme beeinträchtigt werden - und die Funktion gegeben ist, ist Optimierung nicht nötig. Die Kosten für die Handoptimierung von Skripten ist meistens höher, als das Neuschreiben in einer niedriger angesiedelten Sprache (z.B. C), wenn Du nicht gerade grobe Schnitzer eingebaut hast.

                  so short

                  Christoph Zurnieden

                  1. Hallo!

                    Normalerweise ist der Zend-Optimierer in den meisten Fällen mit drin, wenn nicht: einbauen. (Falls Dir die Lizenz zusagt natürlich). Das reicht meist schon.

                    Aber so viel bringt der ja auch nicht. Was viel bringt ist der Zend-Cache, aber der kostet. Als Alternative gibt es den PHP-Accelerator: http://phpaccelerator.co.uk/

                    Den setze ich immwen wenn möglich ein, funktioniert super und ist "angeblich" genauso schnell wie der Zend-Cache.

                    Aber prinzipiell: wenn die Geschwindigkeit ausreicht - also keine Anfrage weggeschmissen wird, weil der Prozessor am Anschlag arbeitet oder kein Speicher mehr frei ist, oder gar andere Programme beeinträchtigt werden - und die Funktion gegeben ist, ist Optimierung nicht nötig. Die Kosten für die Handoptimierung von Skripten ist meistens höher, als das Neuschreiben in einer niedriger angesiedelten Sprache (z.B. C), wenn Du nicht gerade grobe Schnitzer eingebaut hast.

                    Nur lässt sich das gerade in größeren Projekten schlecht einbauen. Ich habe z.B. das problem dass ich eine sehr komplexe HTML-Tabelle erzeugen muss(zum Teil aus mehreren 1000 Datensätzen aus verschiedenen Tabellen...), ich arbeite überall mit Templates und Datenbank-Abstraktion, durch das gesamte Projekt, und das stellt hier schon eine Bremse dar. Es kommt drauf an wie groß die HTML-Tabelle wird, aber bei den ganz großen die ich mal testweise probiert habe hat es teilweise über 15 Sekunden gedauert, und so lange wartet man ungern, und dabei war der Server sonst unbenutzt und ist eigentlich verhältnismäßig schnell.

                    Ich wüßte nicht wie C mir hier helfen könnte. Oder meinst Du einfach den Algorithmus in C Programmieren und das dann per CGI einbinden? Aber sowas mag ich nicht, das habe ich schon aus einem anderen Grund mit einigen PERL-Scripten machen müssen, und dann muss ich auf einmal auch alle möglichen Konfigurationsdateien einlesen, was ich für die PHP-Scripte einmal an zentraler Stelle mache...

                    Viele Grüße
                    Andreas

                    1. Hi,

                      Normalerweise ist der Zend-Optimierer in den meisten Fällen mit drin, wenn nicht: einbauen. (Falls Dir die Lizenz zusagt natürlich). Das reicht meist schon.

                      Aber so viel bringt der ja auch nicht. Was viel bringt ist der Zend-Cache, aber der kostet.

                      Also sagt Dir die Lizenz nicht zu ;-)

                      Als Alternative gibt es den PHP-Accelerator:http://phpaccelerator.co.uk/

                      Den setze ich immwen wenn möglich ein, funktioniert super und ist "angeblich" genauso schnell wie der Zend-Cache.

                      Oder so, ja stimmt, hatte ich vergessen.

                      Aber prinzipiell: wenn die Geschwindigkeit ausreicht - also keine Anfrage weggeschmissen wird, weil der Prozessor am Anschlag arbeitet oder kein Speicher mehr frei ist, oder gar andere Programme beeinträchtigt werden - und die Funktion gegeben ist, ist Optimierung nicht nötig. Die Kosten für die Handoptimierung von Skripten ist meistens höher, als das Neuschreiben in einer niedriger angesiedelten Sprache (z.B. C), wenn Du nicht gerade grobe Schnitzer eingebaut hast.

                      Nur lässt sich das gerade in größeren Projekten schlecht einbauen. Ich habe z.B. das problem dass ich eine sehr komplexe HTML-Tabelle erzeugen muss(zum Teil aus mehreren 1000 Datensätzen aus verschiedenen Tabellen...), ich arbeite überall mit Templates und Datenbank-Abstraktion, durch das gesamte Projekt, und das stellt hier schon eine Bremse dar. Es kommt drauf an wie groß die HTML-Tabelle wird, aber bei den ganz großen die ich mal testweise probiert habe hat es teilweise über 15 Sekunden gedauert, und so lange wartet man ungern, und dabei war der Server sonst unbenutzt und ist eigentlich verhältnismäßig schnell.

                      Dann ist die Frage: wie oft kommt sowas vor, sprich: wie lante dauert das durchschnittlich. Wenn es nur Spitzen sind, kann es akzeptabel sein.
                      Es istauch möglich, das Deine Tabellenerzeugung selber einfach zu lange dauert. Baust Du zuerst die ganze Tabelle zusammen, oder hast Du die Möglichkeit, Zeile für Zeile auszuwerfen? Das dauert dann zwar nicht weniger lang, aber dafür bekommt der Client schonmal Daten und kann sie direkt anzeigen. Ist dann subjektiv deutlich schneller.

                      Ich wüßte nicht wie C mir hier helfen könnte. Oder meinst Du einfach den Algorithmus in C Programmieren und das dann per CGI einbinden?

                      Das kann ich schlecht sagen, dafür bräuchte ich dann schon den Code.
                      Aber per CGI einzubinden ist schlecht, wenn schon dann als PHP-Lib direkt an PHP anbinden und dann auch _nur_ den Algorithmus.

                      Aber sowas mag ich nicht, das habe ich schon aus einem anderen Grund mit einigen PERL-Scripten machen müssen, und dann muss ich auf einmal auch alle möglichen Konfigurationsdateien einlesen, was ich für die PHP-Scripte einmal an zentraler Stelle mache...

                      Deshalb die direkte Anbindung, das spart den ganzen Driss.
                      Oder eben wirklich _alles_ in C (oder C++ oder Assembler oder ...). Es kommt aber auch auf den Zweck an. Bei viel Rechenarbeit lohnt sich das, aber wenn das alles nur aus SQL Abfragen und daraus HTML herstellen besteht, ist der Effekt sehr gering.

                      so short

                      Christoph Zurnieden

          2. function zufall ()
            schlecht gewählter Funktionsname
            ist doch scheiss egal!

            Gut gewählte Funktionsnamen erleichtern spätere Arbeit ungemein. Glaub's uns, wir haben auch aus unseren Fehlern lernen müssen ;-)

            ey das ist doch der passendste funktionsname den es gibt - ich finde mit zufall() eine zufallszahl/id und nix anderes!

            Dann mußt Du den Funktionsaufruf eben anders gestalten. Noch ein Problem damit: hier "if ($lid == $id) zufall();" ist ein rekursiver Aufruf. Wegen der globalen Variablen ist diese Funktion aber nicht reentrant.

            verstehe ich nicht - also "reentrant" und somit auch den satz nich ganz.

            Das funktoniert bei PHP weil dort "global" keine wirklich globalen Variablen erzeugt, aber mach es trotzdem nicht, das geht meist in's Auge.
            ja global hin und her

            ich hasse funktionen, dafür das es dieses global gibt, gibt es denn keinen weg?
            es hat manchmal vorteile das man innerhalb funktionen variablen nutzen kann und ausserhalb keine variable überschrieben wird, aber genau das will ich nicht, ich will das sie überschrieben werden und das erreiche ich nur mit global $var;

            Warum nimmst Du eigentlich nicht die von PHP angebotenen hauseigenen SessionIDs?

            für was denn?

            Danke für die Antwort!
            MfG Andy

            1. Hi,

              Gut gewählte Funktionsnamen erleichtern spätere Arbeit ungemein. Glaub's uns, wir haben auch aus unseren Fehlern lernen müssen ;-)
              ey das ist doch der passendste funktionsname den es gibt - ich finde mit zufall() eine zufallszahl/id und nix anderes!

              Dann nenn die Funktion doch make_id()? Es wird etwas hersgetsellt "make" und es ist eine ID, die hergestellt wird "id", zusammenfügen dann mit "_". Das ist eine leicht merkbare Logik, die spätere Suche erleichtert.

              Dann mußt Du den Funktionsaufruf eben anders gestalten. Noch ein Problem damit: hier "if ($lid == $id) zufall();" ist ein rekursiver Aufruf. Wegen der globalen Variablen ist diese Funktion aber nicht reentrant.
              verstehe ich nicht - also "reentrant" und somit auch den satz nich ganz.

              Eine reentrante Funktion ist, stark verallgemeinert, eine Funktion, die sich jederzeit von jeder beliebigen Stelle aus aufrufen läßt unter anderem auch von sich selbst aus (rekursiv). Das funktioniert aber auf keinen Fall mit globalen Variablen.

              ich hasse funktionen, dafür das es dieses global gibt, gibt es denn keinen weg?

              Du muß lokale Variablen nehmen oder die Speicherstellen beim Aufruf der Funktion mitgeben.

              es hat manchmal vorteile das man innerhalb funktionen variablen nutzen kann und ausserhalb keine variable überschrieben wird, aber genau das will ich nicht, ich will das sie überschrieben werden und das erreiche ich nur mit global $var;

              Dann gib sie der Funktion doch einfach mit!

              <?PHP
              $DIES_IST_EINE_GLOBALE_VARIABLE = 1234;
              $EINE_ZWEITE = 5678;

              function print_global_var($glob_var,$zweite){
                if($zweite == 5678){
                  $glob_var++;
                  print_global_var($glob_var,$zweite);
                }
                  echo $glob_var;
              }

              print_global_var($DIES_IST_EINE_GLOBALE_VARIABLE, $EINE_ZWEITE);

              ?>

              Warum nimmst Du eigentlich nicht die von PHP angebotenen hauseigenen SessionIDs?
              für was denn?

              Wenn ich das richtig sehe, brauchst Du eindeutige IDs, die liefern Dir SessionIDs bzw Du kannst sie Dir mit MD5Sum leicht selber herstellen.
              Warum Du SessionIDs von Hand kontrollieren mußt entzieht sich meinem Verständnis.

              so short

              Christoph Zurnieden

              1. <?PHP
                $DIES_IST_EINE_GLOBALE_VARIABLE = 1234;
                $EINE_ZWEITE = 5678;

                function print_global_var($glob_var,$zweite){
                  if($zweite == 5678){
                    $glob_var++;
                    print_global_var($glob_var,$zweite);
                  }
                    echo $glob_var;
                }

                print_global_var($DIES_IST_EINE_GLOBALE_VARIABLE, $EINE_ZWEITE);

                ?>

                dein script geht nicht. und ich verstehe scripte erst wenn ich sie ausgeführt habe und im nachhinein nachvollziehen kann.
                aber ich glaub folgendes gegenargument zu haben:

                ein echo innerhalb der function bringt mir so oder so nix - ich brauch meine variable übers ganze script lang. und mit return kann ich nur eine variable zurückgeben - im prinzip brauche ich ja auch nur id. ich könnte ja ein array zurückgeben, aber gibt es denn nicht eine allgemeinere lösung?

                MfG Andy

                1. Hi,

                  <?PHP

                  [...]

                  ?>

                  dein script geht nicht. und ich verstehe scripte erst wenn ich sie ausgeführt habe und im nachhinein nachvollziehen kann.

                  Nein, mein Script funktioniert nicht, das war mir schon klar ohne es überhaupt ausprobiert zu haben. Es ging um eine verständlich Darstellung des Prinzips. Das ist sogenannter Pseudocode.
                  Bitte um Entschuldigung, das ich es nicht drangeschrieben habe, dachte es wäre auch so klar.

                  aber ich glaub folgendes gegenargument zu haben:

                  ein echo innerhalb der function bringt mir so oder so nix

                  echo() wurde plaziert, um den Inhalt der Variablen auszugeben. Was Du anstelle von echo() hinsetzt bleibt Dir überlassen.

                  • ich brauch meine variable übers ganze script lang. und mit return kann ich nur eine variable zurückgeben - im prinzip brauche ich ja auch nur id. ich könnte ja ein array zurückgeben, aber gibt es denn nicht eine allgemeinere lösung?

                  PHP ist nunmal nicht Typenlos, Du kommst also nicht darum herum zum Zwecke der Rückgabe mehrerer Werte entweder diese in einen Typ zu packen, der sie halten kann (Arry, Hash o.ä.) oder globale oder gegebene Variablen direkt zu überschreiben.

                  Mehr als diese drei Möglichkeiten hast Du nicht.

                  Aber Du zäumst das Pferd auch ein wenig von hinten auf. Erstmal solltest Du klären, was _genau_ Du machen willst. Du brauchst eine eindeutige ID. ("eindeutig" heißt hier, das sie nicht mehrfach vorkommen darf). Du hast als Vorgabe zur Programmiersprache PHP (Version 4 nehme ich mal an). Das ist eine Skriptsprache, die schon lange raus ist und gut genutzt wird, für die es also allerhand gibt. Vor dem Problem, das Du hast, haben also mit hoher Sicherheit schon andere gestanden. Du schaust also erstmal nach, ob das diese anderen evt schon gelöst haben und entspr. Code verfügbar ist. PHP4 hat schon allerhand mit drin im Paket, das wäre die erste Anlaufstelle. Dort findest Du die Möglichkeit SessionIDs zu generieren. PHP4 ist im Netz hervorragend dokumentiert, vor allem ist die Dokumentation mit Benutzerkommentaren versehen. Da findest Du evt schon fertige Codesnippets. Wenn nicht, schmeißt Du Google an. Erst wenn Du da auch nichts findest, mußt Du Dich wohl oder übel selber hinsetzen.
                  Oder im Selfforum posten ;-)

                  Aber nochmal zu Deinem Problem:
                  Wenn Du einzig eine eindeutige ID suchst, dann würde ich die mit md5sum($MICROTIME_STAMP . $IP_ADDRESS_CLIENT . $GENERAL_SEED) generieren.
                  ($GENERAL_SEED enthält immer das gleiche: z.B. eins MD5Sum Deines Namens plus noch einiger Angaben. Das ist nur dafür da, damit andere die MD5Sum nicht einfach nachbauen können. Dieser Seed ist geheim zu halten.) Die Wahrscheinlichkeit, das zur gleichen Zeit (Auflösung: Mikrosekunde + ein wenig für die Codeausführung) mit der gleichen IP Adresse Leute ankommen ist extrem gering, eine Kontrolle, ob diese ID schon vorhanden ist, kann sich so erübrigen. Wenn Du nur mit Zufallszahlen jonglierst ist die Wahrscheinlichkeit hingegen viel zu hoch, da mußt Du dann kontrollieren.

                  so short

                  Christoph Zurnieden

        4. Hallo!

          SESSION_REGISTER("lids");
          benutze besser das "super global"- Array $_SESSION
          Kenne ich nicht - kannst du mir das mal genaue erklären?

          Im Manual zu session_register() ist das erklärt: http://de3.php.net/session-register

          siehe auch: http://de3.php.net/session und http://www.dclp-faq.de/q/q-sessions-wie.html

          zufall();
          Funktionsaufruf steht vor der Funktionsdefinition, das funktioniert zwar, empfinde ich persönlich aber als schlechten Stil.

          Wieso? Ich finde es immer nervig wenn am Anfang eines Scriptes zig lange Funktionen stehen und man die eigentliche "Script-Logik" erst mühsam suchen muss. Wenn die Funktionen am Ende stehen ist das zumindest für mich angenehmer.

          function zufall ()
          schlecht gewählter Funktionsname
          ist doch scheiss egal!

          Jetzt, aber später kann es verhängnisvoll sein ;-)

          {
          global $max, $id, $lids, $lid;
          global ist meistens unnötig und ist im Hinblick auf vernünftige
          Modularisierung kontraproduktiv.
          wie kann ich es denn asutrixen? wenn ich es weglasse geht nix, dann müsste ich den funktionsaufruf anders gestalten.

          Es kommt drauf an, wenn die Daten sich eigentlich nicht ändern sollen(z.B. $max), dann kann man das IMHO durchaus über globale Variablen machen, je nachdem vielleicht sogar nur innerhalb der Funktion definieren, oder vielleicht besser über Konstanten.

          Mich würde mal interessieren wie Ihr das machen würdet. Ich würde es vermutlich in etwas so machen, wobei ich vermutlich nichtmal eine Funktion verwenden würde, naja.

          <?php

          define('RAND_MAX', 5);
          mt_srand ((double)microtime()*1000000);
          session_start();

          $_SESSION['lids'][] = zufallszahl_generieren($_SESSION['lids']);

          function zufallszahl_generieren ( &$zahlenarray) {
              do {
                  $tmp_rand = mt_rand(0, RAND_MAX);
              }
              while (in_array($tmp_rand, $zahlenarray));
              return $tmp_rand;
          }

          ?>

          Grüße
          Andreas

          1. <?php

            define('RAND_MAX', 5);
            mt_srand ((double)microtime()*1000000);
            session_start();

            $_SESSION['lids'][] = zufallszahl_generieren($_SESSION['lids']);

            function zufallszahl_generieren ( &$zahlenarray) {
                do {
                    $tmp_rand = mt_rand(0, RAND_MAX);
                }
                while (in_array($tmp_rand, $zahlenarray));
                return $tmp_rand;
            }

            ?>

            Warning: Wrong datatype for second argument in call to in_array in /home/pacs/mih01/users/mw01/doms/michaelwoelk.de/subs/www/wsab/zufall2.php on line 13

            und ab einem reload ständig eine leere seite

            MfG Andy - ich kann auch garkein print oder echo sehen ;-)

            1. Hi!

              Warning: Wrong datatype for second argument in call to in_array in /home/pacs/mih01/users/mw01/doms/michaelwoelk.de/subs/www/wsab/zufall2.php on line 13

              Ja, kommst Du drauf woran es liegt(die Fehlemeldung ist ja ausßergewöhnlich genau in diesem Fall!)?
              Die Funktionsbeschreibung zur problematischen Funktion in_array():

              bool in_array ( mixed needle, array haystack [, bool strict])

              (Quelle: http://de3.php.net/in-array)

              Und jetzt überlege Dir, was der Funktion beim erstmaligen Aufruf für Parameter übergeben werden.

              Das ganze funktioniert nur wenn es den Array mit dem IDs schon gibt, es ging mir mehr um Prinzipien, nicht um den fertigen Code.
              Du musst lediglich bevor die Funkrtion aufgerufen wurde, dafür sorgen dass der Array auch tatsächlich existiert, hierbei könnten Dir die Funktionen is_array() und array() helfen, siehe http://de3.php.net/manual/de/function.array.php und http://de3.php.net/is_array

              und ab einem reload ständig eine leere seite

              jepp, siehe unten

              MfG Andy - ich kann auch garkein print oder echo sehen ;-)

              Ich auch nicht, aber es steht Dir ja frei auszuegeben was und wo Du willst.

              Grüße
              Andreas

  3. <?php
    SESSION_START();

    print "LIDS: $lids<br>";

    $max = 5;

    $exp_lids = explode("|", $lids);
    $count = count($exp_lids)-1;

    mt_srand ((double)microtime()*1000000);
    function zufall ()
    {
     global $max, $id, $exp_lids, $lid, $count;
     $id = mt_rand(0,$max);

    for ($i=0; $i <= $count; $i++)
     {
      $lid = $exp_lids[$i];
      print "$lid == $id<br>";
      if ($lid == $id) zufall();
     }

    return $id;
    }

    print "$count == $max<br>";
    if ($count != $max)
    {
     $id = zufall();
     $lids = $id."|".$lids;
     $_SESSION['lids'] = $lids;
    }

    if ($id == '') print "ende";
    else print "ID: $id<br>";
    ?>

    was spricht hier noch dagegen? ausser global?