Philipp Hasenfratz: IP's von access_log in bestimmtem Zeitfenster extrahieren

Halihallo Programmiertechniker

Dieser Thread bezieht sich auf [pref:t=46188&m=252704]. Habe mich entschieden ein
neuer Thread zu starten.

Ich habe eine Apache-Access-Log vorliegen, ca. 2GB gross. Nun gilt es aus dieser Datei
eine neue Datei zu transformieren, welche die _unterschiedlichen_ (aus der Ur-
sprungsdatei extrahierten) IP's abbildet. Erschwerend kommt hinzu, dass die zu
IP's nur von einem bestimmten Zeitfenster extrahiert werden sollen und nur bestimmte
URL's überhaupt interessieren (Request muss geparsed und untersucht werden).
Programmiersprache vorzugsweise C (evtl. Perl).
Frage gleich hier: Wie würdet ihr das möglichst performant umsetzen?

Meine Gedanken:
Die access-log ist per Definition schon nach der Zeit indiziert, nur sind die Datensätze
nicht fixer Länge. Ich dachte mir, dass ich trotz dieses Umstandes die Datei als eine
Datei fixer Datensatzlänge interpretiere und einen Buffer von 32kb anlege. Wenn es nun
darum geht eine bestimmte Zeit zu selektieren, iteriere ich wie in einem B-Baum über
die Datei, untersuche den aktuell eingelesenen Buffer auf Newlines und lese alles danach
in die struct log_entry ein. Falls das extrahierte Datum kleiner als das zu suchende ist,
wird die nächste Hälfte selektiert, die vorherige wenn das Datum grösser ist. So finde
ich in dem access_log in etwa log(n)-Zeit das gewünschte Datum (nicht n/2, wenn ich alle
Daten extrahieren würde). Wenn ich die Position des Start-Entries und des End-Entries
gefunden habe iteriere ich über die eingeschlossenen log-Entries und extrahiere die IP's.
Über ein Look-Back-Array von 10'000 IP's finde ich die unterschiedlichen[1] und
speichere sie in der Ausgabedatei ab.

Meine Frage:
Habt Ihr mir vielleicht Anregungen? - Verbesserungsvorschläge? - Anmerkungen?

[1] mit einigermassen kleiner Fehlerrate, die tolerabel ist. Alles kleiner 5% Fehler ist
    für die Aufgabenstellung akzeptabel. Die 5% Fehler bezihen sich auf die extrahierten
    IP's von einem Tag. Die 10'000 ist IMHO ausreichend, denn viel mehr werden in einem
    Tag gar nicht gespeichert. Mir ist bewusst, dass die IP's nicht staatisch zugewiesen
    werden, die IP's werden zu bestimmten Zeiten aufgelöst und somit macht es keinen
    Sinn, wenn man mehrmals die selbe IP auflöst, deshalb die Extraktion
    unterschiedlicher IP's.

Viele Grüsse

Philipp

  1. Hi Philipp!

    Versteh ich das richtig dass Du eine Logdatei mit Deinem Programm dann speziell auswerten willst? Also öfter und nicht nur einmal?
    Dann würde ich evtl. daran denken optimierte Datenquellen zu erstellen, je nachdem was Du so brauchst, z.B. für jeden Tag eine Datei, dann brauchst Du schonmal nicht mehr nach dem Datum suchen, und/oder nach Host-Adresse... dann hast Du zwar ein paar mehr Dateien, nur denke ich das würde erheblich schneller sein als immer 2GB zu durchsuchen, wobei ich nicht weiß wie das mit deiner Baum-Suche so aussieht, nur ist das Filesystem dann auch so eine Art Baum, musst Du halt probieren. Vielleicht kannst Du im Quelltext  einer RDBMS mal nachgucken wie die das machen, da werden die Daten ja auch in Textdateien gespeichert, vielleicht kannst Du Dir da was abgucken.

    2. Möglichkeit wäre direkt eine Datenbank zu verwenden, mit entsprechend indices, halt für jede Suche speziell optimierte.

    Ich denke nicht dass Du bei der Menge Daten den Algorithmus einer Datenbank die hierfür ja optimiert ist schlagen könntest. Ich habe das schon bei 1MB deutlich zu spüren bekommen.

    Aber vermutlich bin ich nicht der richtige Ansprechpartner wens um performante parsen von Flat-Files geht ;-)

    Viele Grüße
    Andreas

    1. Halihallo Andreas

      Versteh ich das richtig dass Du eine Logdatei mit Deinem Programm dann speziell auswerten willst? Also öfter und nicht nur einmal?

      Ja, die Auswertung läuft ca. 2-4x am Tag.

      Dann würde ich evtl. daran denken optimierte Datenquellen zu erstellen, je nachdem was Du so brauchst, z.B. für jeden Tag eine Datei, dann brauchst Du schonmal nicht mehr nach dem Datum suchen, und/oder nach Host-Adresse... dann hast Du zwar ein paar mehr Dateien, nur denke ich das würde erheblich schneller sein als immer 2GB zu durchsuchen,

      Ja, das ist in der Tat eine sehr gute Idee. So schnell wie möglich den Datenbestand
      verringern. Nur, wie du aus "Lösung" entnehmen kannst, haben bei mir die Tests ergeben,
      dass das parsen des Logs das kleinste Problem ist. Aber darauf muss man auch erst kommen
      (obwohl man/ich es eigentlich hätte früher merken können).

      wobei ich nicht weiß wie das mit deiner Baum-Suche so aussieht, nur ist das Filesystem dann auch so eine Art Baum, musst Du halt probieren. Vielleicht kannst Du im Quelltext  einer RDBMS mal nachgucken wie die das machen, da werden die Daten ja auch in Textdateien gespeichert, vielleicht kannst Du Dir da was abgucken.

      Nun, eine Log-Aufsplittung auf Tage wäre schon ausreichend, da ich jeweils die Daten
      eines Tages brauche. Somit würde das selektieren der Daten schon wegfallen.

      1. Möglichkeit wäre direkt eine Datenbank zu verwenden, mit entsprechend indices, halt für jede Suche speziell optimierte.

      Hm. Die Daten müssten jedoch auch dann aus dem Log eingespiesen werden :-)
      OK, das selektieren würde wegfallen...

      Ich denke nicht dass Du bei der Menge Daten den Algorithmus einer Datenbank die hierfür ja optimiert ist schlagen könntest. Ich habe das schon bei 1MB deutlich zu spüren bekommen.

      Das stimmt.

      ---

      Naja, dann versuche ich jetzt mal ein schneller DISTINCT-Algorithmus zu
      implementieren :-)

      Viele Grüsse

      Philipp

      1. Hi!

        Eigentlich sind das alles unnötige Probleme, ich würde einfach PHP nehmen und ganz "gemütlich" parsen, und die Sache mit der proformance jemandem überlassen der was davon versteht, z.B.: http://www.sun.com/servers/highend/whitepapers/SUN_SF15K_DS_01-03_V3.pdf

        *scnr*

        Grüße
        Andreas

  2. Halihallo zusammen

    Als "Lösung" wie es im Thread-Titel steht, kann ich dies zwar nicht klassifizieren,
    jedoch halte ich es für eine praktische Umsetzung, die der Aufgabenstellung genügt:

    Ich habe den log-parser geschrieben und konnte einige Testläufe machen. Festgestellt habe
    ich, dass das parsen gar nicht das Problem ist, selbst wenn die ganze log geparsed wird
    (was ich der Einfachheits halber vorerst und wohl auch künftig so löse/gelöst habe). Die
    Zeit, die für das Parsen gebraucht wird, beläuft sich auf durchschnittlich 15-20
    Sekunden, was für etwas mehr als 200MB (habe mich verlesen) zwar langsam, aber akzeptabel
    ist. Das wohl zeitintensivste ist eindeutig das Auffinden der unterschiedlichen IP's,
    dieser Algorithmus gilt es zu verbessern und wie das geht ist im Netz gut beschrieben
    (sortierte Listen, begrenzter Look-Back, wie beschrieben, ...). Hatte ich leider nicht
    bedacht...
    Zudem bringt ein vorgeschaltener Filter für die URL eine starke Reduktion der Datenmenge,
    was sich ebenfalls performant auswirkt.

    Das Problem reduziert sich also auf das Implementieren eines schnellen Algorithmus für
    das Extrahieren unterschiedlicher IP's. Für die Aufgabenstellung genügt eine Umsetzung,
    die innerhalb eines Zeitfensters von 2-4 Minuten das Resultat anzeigt, das werde ich
    wohl umsetzen können.

    Man sieht, wiedermal zu kompliziert gedacht... Obwohl, ich arbeitete wirklich mit dem
    Gedanken an 2GB, dort wären die Überlegungen wohl gerechtfertigt, jedoch würde auch dann
    das Hauptproblem beim genannten Algorithmus liegen.

    Viele Grüsse

    Philipp

    PS: Sorry für die frühzeitige Belästigung :-)

    1. Hi!

      Ich habe den log-parser geschrieben und konnte einige Testläufe machen. Festgestellt habe
      ich, dass das parsen gar nicht das Problem ist, selbst wenn die ganze log geparsed wird
      (was ich der Einfachheits halber vorerst und wohl auch künftig so löse/gelöst habe). Die
      Zeit, die für das Parsen gebraucht wird, beläuft sich auf durchschnittlich 15-20
      Sekunden, was für etwas mehr als 200MB (habe mich verlesen) zwar langsam, aber akzeptabel
      ist.

      Findest Du? Wenn ich die Selfsuche verwende(PERL-CGI) hat sie gerade bei einem Test 200 MB Daten in:

      "Dauer der Suche: 4.703125 sec usertime, 0.7890625 sec systemtime"

      ich hoffe mal nicht dass die 0,8 Sekunden die komplette Zeit ist die hier benötigt wird, denn sonst versinke ich gleich im Boden ;-)

      Bedenke dass das eine Volltext-Suche ist(ich habe nach 3 Worten gesucht), das brauchst Du ja nicht, Du könntst die Daten mittels einer Datenbank ja direkt in ein möglichst kleines Format bringen(IPs: FLOAT oder LONGINT), Datum in DATE, dann hättest Du nur noch den Hostnamen wo Du dann einen String-Vergleich bräuchtest.
      Dazu noch entsprechende Indices(muss man mal ein bisschen mit EXPLAIN versuchen bis man für jede Query den optimalen gefunden hat)

      Das sollte dann vermutlich schneller sein.

      Das wohl zeitintensivste ist eindeutig das Auffinden der unterschiedlichen IP's,
      dieser Algorithmus gilt es zu verbessern und wie das geht ist im Netz gut beschrieben
      (sortierte Listen, begrenzter Look-Back, wie beschrieben, ...). Hatte ich leider nicht
      bedacht...
      Zudem bringt ein vorgeschaltener Filter für die URL eine starke Reduktion der Datenmenge,
      was sich ebenfalls performant auswirkt.

      Ja, alles raus was Du nicht brauchst, gerade bei der Datenmenge macht sich das bemerkbar!

      PS: Sorry für die frühzeitige Belästigung :-)

      Ach ... ;-)

      Grüße
      Andreas

    2. Hallo Philipp,

      Das Problem reduziert sich also auf das Implementieren
      eines schnellen Algorithmus für das Extrahieren
      unterschiedlicher IP's.

      IMHO wuerde sich da herrlich eine Hashtable-Bibliothek eignen.
      Vielleicht kannst du ja

      http://cvs.teamone.de/selfforum/src/hashlib.c?rev=1.6&content-type=text/x-cvsweb-markup

      bzw.

      http://cvs.teamone.de/selfforum/src/hashlib.h?rev=1.4&content-type=text/x-cvsweb-markup

      gebrauchen. Eine Doku gibts unter

      http://cforum.teamone.de/doku/developer/hashlib_8c.htm

      Gruesse,
       CK

      1. Halihallo Christian

        IMHO wuerde sich da herrlich eine Hashtable-Bibliothek eignen.

        Ja, da hast du recht... Ich hatte einen Test über Datei gestartet, war jedoch sehr, sehr
        enttäuscht, an eine Lösung über Hashtables hatte ich gar nicht mehr gedacht. Nun,
        gedacht schon (die LookBack-Table würde einer Arrayimplementierung entsprechen, die
        das selbe macht, wie deine Hashtable-Bibliothek). Das wäre der nächste Schritt gewesen.
        Was mich von einem Hash abhielt war a) die Performance und b) der grosse
        Speicherverbrauch (immerhin sind das keine kleinen Mengen an Daten). Doch denke ich nun,
        dass sich die Datenmenge über RAM-Speicher verarbeiten liesse (obwohl die Lösung dann
        nicht mehr gross skalierbar wäre, Speicher ist kostbar) und dass vorallem ein guter
        Hashing-Algorithmus sehr gute Performance bringt (daran hatte ich ebenfalls nicht
        gedacht).
        Diese Lösung würde ich derjenigen über die Datenbank vorziehen, da der Datentransfer
        zur Datenbank schlicht Overhead ist und den Performancegewinn (wenn überhaupt vorhanden)
        gleich vernichtigen würde. Es geht lediglich darum die unterschiedlichen IP's zu
        extrahieren, das ist IMHO in einer "All-In-One" Lösung wesentlich schneller. Wenn
        es darum ginge eine komplette Analyse der Daten vorzunehmen, wäre die Datenbank wieder
        im Rennen.

        Viele Grüsse

        Philipp

  3. Hi,

    Meine Frage:
    Habt Ihr mir vielleicht Anregungen? - Verbesserungsvorschläge? - Anmerkungen?

    wir machen das für einen Kunden so, daß wir die Logfiles in eine Datenbank transferieren. Das dauert einmalig rel. lange, die Auswertung ist aber danach sehr schnell und auf Knopfdruck ist das zu sehen, was Dich interessiert.

    10Gbyte auf einem Einzelrechner (PIII, 800 Mhz, SCSI, 500MB) am Tag sind durchaus machbar. Ich meine Damit den Transfervorgang, danach sieht das so aus, wie im Demo auf unserer Webseite.

    Gruß
    Reiner

    1. Halihallo Reiner

      Meine Frage:
      Habt Ihr mir vielleicht Anregungen? - Verbesserungsvorschläge? - Anmerkungen?

      wir machen das für einen Kunden so, daß wir die Logfiles in eine Datenbank transferieren. Das dauert einmalig rel. lange, die Auswertung ist aber danach sehr schnell und auf Knopfdruck ist das zu sehen, was Dich interessiert.

      Ja, das mit der Datenbank ist wirklich eine gute Lösung. Ich glaube das werde ich so
      auch umsetzen (danke an euch beide). Ehrlich gesagt überlasse ich das Auffinden von
      eindeutigen IP's (oder andere Aufgaben, die evtl. noch kommen) lieber der Datenbank,
      denn diese, wie Andreas sagt, ist dafür ja wirklich optimiert.
      Obwohl mir graut etwas davor, dass ich lediglich für ein "DISTINCT" den ganzen
      Datenbestand (nur mehr aus IP's bestehend) in die Datenbank zu portieren. Aber naja...

      10Gbyte auf einem Einzelrechner (PIII, 800 Mhz, SCSI, 500MB) am Tag sind durchaus machbar. Ich meine Damit den Transfervorgang, danach sieht das so aus, wie im Demo auf unserer Webseite.

      Eine Frage: Ihr analysiert die Benutzerströme durch eindeutige Benutzer-ID's, die Ihr
      aus log-Daten erhaltet. Wie bzw. wann bereitet ihr diese auf? - Wann generiert Ihr aus
      den euch vorliegenden Daten eindeutige "ID's" für Benutzer, um sie zu tracken? -
      Geschieht dies über die Datenbank, oder das einmal laufende Programm für die
      Aufbereitung? - Habt ihr da auch das Problem, auf "ältere" Daten zurückzugreifen und
      somit auch das Problem, dass ihr in grossen Datenmengen gleiche Daten ausfindig machen
      müsst? => das wäre ja ein analoges Problem und deshalb für mich von interesse.

      Viele Grüsse

      Philipp

      1. Hi!

        Ja, das mit der Datenbank ist wirklich eine gute Lösung. Ich glaube das werde ich so
        auch umsetzen (danke an euch beide). Ehrlich gesagt überlasse ich das Auffinden von
        eindeutigen IP's (oder andere Aufgaben, die evtl. noch kommen) lieber der Datenbank,
        denn diese, wie Andreas sagt, ist dafür ja wirklich optimiert.

        Übrigens habe ich mir in PHP letztens für dieses FLOAT-IP Format(oder wie auch immer man das nennt) eine Umrechnung gebastelt:

        $ip = '127.0.0.1';
        $num = explode(".", $ip);
        $float_ip = $num[0]*16777216 + $num[1]*65536 + $num[2]*256 + $num[3];

        Hat halt den Vorteil dass man dann die IP nicht mehr als String hat, sondern als Zahl, nur leider sind die meisten IPs zu groß für INT :-(

        Das lustige ist dass diese Zahlen auch tatsächlich über den Browser funktionieren, wenn  man umgerechneten Wert für 213.139.94.131 in die Adresszeile des Browsers eingibt kommt man auf teamone.de ;-)

        Obwohl mir graut etwas davor, dass ich lediglich für ein "DISTINCT" den ganzen
        Datenbestand (nur mehr aus IP's bestehend) in die Datenbank zu portieren. Aber naja...

        Wenn s das performanteste ist? Was aber noch zu klären wäre ;-)
        Meine Tipps bezogen sich eher darauf dass so wie Reiner es beschreibt, einmal in die Datenbank eingespielt wird, und dann so oft man will recht zügig abgefragt werden kann. Aber das einspielen in die Datenbank alleien ist vermutlich deutlich langsamer als das ganze selbst zu implementieren! Vor allem wenn man indices verwenden will. Musst halt ein bisschen probieren, aber vermutlich wird Michael Schröpl wie ich ihn kenne noch das ein oder andere As im Ärmel haben *bg*

        Grüße
        Andreas

        1. Halihallo Andreas

          Übrigens habe ich mir in PHP letztens für dieses FLOAT-IP Format(oder wie auch immer man das nennt) eine Umrechnung gebastelt:
          $ip = '127.0.0.1';
          $num = explode(".", $ip);
          $float_ip = $num[0]*16777216 + $num[1]*65536 + $num[2]*256 + $num[3];

          Hm. Long-IP für Longinteger wäre IMHO passender :-)
          Ja, die Umrechnung mache auch ich, denn in C lassen sich unsigned long's wesentlich
          schneller verarbeiten als Strings (wie in jeder Programmiersprache, die das
          unterscheidet => 3GL (meistens)). Und: Die "stringifizierte" Forum braucht ganze
          11 Bytes mehr im Worst-Case :-)

          Hat halt den Vorteil dass man dann die IP nicht mehr als String hat, sondern als Zahl, nur leider sind die meisten IPs zu groß für INT :-(

          Hä? - Schalte ein unsigned davor oder substrahiere sie von INT_MAX, so kommst du wieder
          zur lesbaren Form. Oder sprichst du von IPv6? - Ja, dort bräuchte man 'n bissle mehr...
          Oder man bräuchte ein Supa-Dupa Sun Fire Rechner mit 128bit Registern :-)

          Das lustige ist dass diese Zahlen auch tatsächlich über den Browser funktionieren, wenn  man umgerechneten Wert für 213.139.94.131 in die Adresszeile des Browsers eingibt kommt man auf teamone.de ;-)

          So kann man bestimmt einige beeindrucken, einige 32-bit Zahlen auswendiglernen und so
          google, teamone etc aufrufen :-)

          Wenn s das performanteste ist? Was aber noch zu klären wäre ;-)

          Für "Reiner-Auswertungen" bestimmt, nicht jedoch für "Philipp-Auswertungen" :-)

          Meine Tipps bezogen sich eher darauf dass so wie Reiner es beschreibt, einmal in die Datenbank eingespielt wird, und dann so oft man will recht zügig abgefragt werden kann.

          Ach so, darauf wolltest du hinaus. Nun, dann nicht, denn die 2-3x täglich wollen dann
          auch nur die neuesten Daten und somit beziehen sich die Abfragen nicht auf den selben
          Datenbestand.

          Viele Grüsse

          Philipp

          1. Hi!

            Hm. Long-IP für Longinteger wäre IMHO passender :-)

            Stimmt, habe ich auch verwendet, nur hat das bei meinen 1MB keinen Unterschied gemacht, nur war FLOAT als Format angegeben und hatte es daher übernommen ;-)

            Und so wie das halt so ist, in PHP gibt es ip2long() ;-)

            Hat halt den Vorteil dass man dann die IP nicht mehr als String hat, sondern als Zahl, nur leider sind die meisten IPs zu groß für INT :-(

            Hä? - Schalte ein unsigned davor oder substrahiere sie von INT_MAX, so kommst du wieder
            zur lesbaren Form.

            Hä? Was ist unsigned und wie schalte ich das wo vor? INT hat sowohl in PHP als auch in MySQL und ich denke auch überall anders, einfach einen zu kleinen Wertebereichüber den gehen dei IPs weit hinaus. Daher verwende ich halt LONINT, aber da PHP kein LONGINT kennt, verwende ich hier FLOAT, denn bei INT kommen komische negative Zahlen bei der Konvertierung raus, naja.

            Oder sprichst du von IPv6? - Ja, dort bräuchte man 'n bissle mehr...

            Oh je, bei denen denkt wohl niemand an uns ;-)

            Oder man bräuchte ein Supa-Dupa Sun Fire Rechner mit 128bit Registern :-)

            JAAA! Ich versuche schon seit Monaten eine Richtfunkstrecke 1 KM bis ins Rechenzentrum unserer Uni hinzubekommen, muss jetzt vom Dach nur noch irgendwie das dicke Kabel in den Keller bekommen, denn da gibt es das:

            16 <img src="http://www.rz.rwth-aachen.de/hpc/sun/16x6800.jpg" border="0" alt=""> und 4 <img src="http://www.rz.rwth-aachen.de/hpc/sun/sunfire15k_einblick.jpg" border="0" alt="">

            http://www.rz.rwth-aachen.de/hpc/sun/index_e.html
            http://www.rz.rwth-aachen.de/hpc/hw/Clusterhardware.html

            Dann wäre das Performance-Problem ein für alle mal geklärt und ich müsste mich nicht mehr über meine stümperhaften Algorithmen ärgern ;-)))

            Viele Grüße
            Andreas

            1. Halihallo Andreas

              Hm. Long-IP für Longinteger wäre IMHO passender :-)
              Stimmt, habe ich auch verwendet, nur hat das bei meinen 1MB keinen Unterschied gemacht, nur war FLOAT als Format angegeben und hatte es daher übernommen ;-)

              Wer setzt denn FLOAT als Format zur Speicherung von IP's voraus? - Pfui :-)

              Hat halt den Vorteil dass man dann die IP nicht mehr als String hat, sondern als Zahl, nur leider sind die meisten IPs zu groß für INT :-(

              Hä? - Schalte ein unsigned davor oder substrahiere sie von INT_MAX, so kommst du wieder
              zur lesbaren Form.
              Hä? Was ist unsigned und wie schalte ich das wo vor?

              Hä? :-)
              Deklariert den Integer als Vorzeichenlos, somit wird der Wertebereich im positiven
              Bereich verdoppelt und der negative fällt eben weg. Gibt's ja auch bei MySQL.

              INT hat sowohl in PHP als auch in MySQL und ich denke auch überall anders, einfach einen zu kleinen Wertebereichüber den gehen dei IPs weit hinaus.

              In MySQL ist INT ein Datentyp mit 32bit, kann also eine IP vollständig abbilden.
              Die Zahl wird nur bei SIGNED evtl. negativ, da das letzte bit (bit 31) gesetzt ist,
              was eben die Zahl als negativ "markiert". Bei UNSIGNED (vorzeichenlos) wirst du
              immer eine positive Zahl kriegen.
              Bei C sieht's etwas anders aus, da kann int mal 32, mal 64bit haben, je nach dem, ob
              die Platform 32 oder 64bit hat. Ein 32-bit-Integer erhält man da explizit über short.
              Also UNSIGNED INT kann die Werte 0-(2^32-1) abbilden, SIGNED INT kann die Werte
              -2^31 bis (2^31-1) abbilden. Wenn du nun eine "grosse" IP in einem vorzeichenbehafteten
              Integer abbildest, kann es vorkommen, dass die Zahl als negativ "interpretiert" wird,
              aber die Zahl wird 100% komplett abgebildet.

              Daher verwende ich halt LONINT, aber da PHP kein LONGINT kennt, verwende ich hier FLOAT, denn bei INT kommen komische negative Zahlen bei der Konvertierung raus, naja.

              s. oben.

              Oder man bräuchte ein Supa-Dupa Sun Fire Rechner mit 128bit Registern :-)

              JAAA! Ich versuche schon seit Monaten eine Richtfunkstrecke 1 KM bis ins Rechenzentrum unserer Uni hinzubekommen, muss jetzt vom Dach nur noch irgendwie das dicke Kabel in den Keller bekommen, denn da gibt es das:
              16 [ image:http://www.rz.rwth-aachen.de/hpc/sun/16x6800.jpg ] und 4 [ image:http://www.rz.rwth-aachen.de/hpc/sun/sunfire15k_einblick.jpg ]
              http://www.rz.rwth-aachen.de/hpc/sun/index_e.html
              http://www.rz.rwth-aachen.de/hpc/hw/Clusterhardware.html
              Dann wäre das Performance-Problem ein für alle mal geklärt und ich müsste mich nicht mehr über meine stümperhaften Algorithmen ärgern ;-)))

              Mama mia, will ich auch, her damit! :-)
              Nun ja, früher hat man sich um jedes verlorene Byte geärgert und heute gibt es viele
              Virtual Maschines, Perl, PHP, ... die eine virtuelle Umgebung simulieren und damit
              tausende an Kilobytes verschwenden... Für jede Variable, die in PHP oder Perl definiert
              wird, gehen einfach mal schwups einige Bytes drauf, ohne überhaupt einen Inhalt darin
              festgelegt zu haben, oder es wird ein pseudo Maschinencode entwickelt, der von einem
              Interpreter abgearbeitet wird... Ich glaube, du bist nicht der einzige, der von
              den Vorzügen neuer Möglichkeiten auch Verwendung machen will :-)
              Wer könnte sich heute noch vorstellen, dass der Bordcomputer der Mondlandung mit ein
              paar Kilobyte auskam; ich hätte Schwierigkeiten ein Programm mit Perl zu schreiben, dass
              unter dieser Voraussetzung überhaupt ein "Hello World" auf dem Bildschrim ausgibt,
              geschweige denn mit Euler-Approximationen die Flugbahn vorherzuberechnen :-)

              Strange world...

              Viele Grüsse

              Philipp

        2. Hi Andreas,

          aber vermutlich wird Michael Schröpl wie ich ihn kenne noch das ein oder andere As im Ärmel haben

          was hältst Du davon, Deine bisherige Architektur über den Haufen zu werfen und sie komplett Deiner Aufgabenstellung unterzuordnen?

          a) Du hast einen ständig fließenden Datenstrom, in Form von Ausgaben in ein Logfile.
          b) Du hast zu bestimmten Zeitpunkten die Anforderung, Auswertungen _auszugeben_.

          Aber niemand hat verlangt, daß die _Berechnung_ der Auswertung erst zum Zeitpunkt der Ausgabe erfolgen muß!

          Also:
          1. Installiere einen daemon, der sich mit "tail -f" an das besagte Apache-Logfile hängt und
             bei jeder ankommenden Zeile _sofort_ inkrementell die entsprechende Auswertung vornimmt.
          2. Bringe diesem daemon bei, auf bestimmte Kommunikations-Signale zu reagieren, z. B.
             a) ein Signal, um das aktuelle Auswertungs-Zwischenergebnis auszuliefern und
             b) ein Signal, um seinen aktuellen Datenbestand (Hash-Tabelle) zu löschen.
          (Wie Du diese IPC im Einzelnen löst - z. B. über sockets - ist dann Deine Entscheidung.)

          Genau wie bei der Forum-Suchmaschine besteht der Trick darin, die Berechnungsleistung nicht erst während der Wartezeit des Anwenders zu investieren, sondern schon lange vorher. Das verbessert die Antwortzeit einer Dialog-Anforderung dramatisch.

          Auch die Architektur des Self-Forums spiegelt sich in dieser Architektur-Skizze teilweise wider: Beide Programme wollen ihre Eingabedaten möglichst nur einmal auswerten, aber beliebig vielen Anfragen hochperformant antworten können.

          Und in gewisser Weise ist dieses Konzept auch in den inkrementellen Auswertungs-Läufen des Webalizers enthalten (welcher allerdings seine Zwischenergebnisse in verdichteter Form auf die Festplatte zurück schreibt, statt permanent zu laufen).

          Viele Grüße
                Michael

          --
          T'Pol: I apologize if I acted inappropriately.
          V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.
          (sh:| fo:} ch:] rl:( br:^ n4:( ie:% mo:) va:| de:/ zu:| fl:( ss:) ls:~ js:|)
           => http://www.peter.in-berlin.de/projekte/selfcode/?code=sh%3A|+fo%3A}+ch%3A]+rl%3A(+br%3A^+n4%3A(+ie%3A%25+mo%3A)+va%3A|+de%3A%2F+zu%3A|+fl%3A(+ss%3A)+ls%3A~+js%3A|
          Auch diese Signatur wird an korrekt konfigurierte Browser gzip-komprimiert übertragen.
  4. Halihallo zusammen

    [...]
    Besten Dank für Eure Vorschläge und guten Eingebungen! - War eine interessante Diskussion
    für mich, die mir den zu beschreitenden Lösungsweg deutlich aufzeigte.
    Nun, dann mache ich mich mal an die Hashtable... :-)

    Besten Dank an alle, speziell noch an Christian für seine Source-Codes, die mir die
    Arbeit sicher erleichtern werden.

    Ach, noch ein kleines Addone zur Aussage von Dir, Andreas:
    Ja, 15-20 Sekunden sind in der Tat sehr lahm, zumal das Durchsuchen von gleichen
    Datenmengen in der Selfsuche nur einen zwanzigstel davon brauchen. Ich muss dies im
    Moment leider noch auf eine wirklich grausame Implementierung des log-parsers
    zurückführen, der mit fgetc jeweils ein Character einliest und über diverse Stati und
    delimitor_type der richtigen Struktureigenschaft zuweist (ich schätze mal, getline und
    strtok wären performanter) :-)
    Eine Überarbeitung ist bereits im Gange :-)

    Viele Grüsse

    Philipp

    1. Hi!

      Ach, noch ein kleines Addone zur Aussage von Dir, Andreas:
      Ja, 15-20 Sekunden sind in der Tat sehr lahm, zumal das Durchsuchen von gleichen
      Datenmengen in der Selfsuche nur einen zwanzigstel davon brauchen.

      War nur so ein Gefühl, ich weiß nicht in wiefern man das vergleichen kann, so hat der Selfserver vermutlich mehr RAM als Du und erheblich schnellere SCSI-PLatten.
      btw. Wie kann denn der Selfserver auf 0.8 Sekunden kommen? Vermutlich kommen die Daten per SCSI mit ca. 70 MB/sek, das wären dann mind. 3 Sekunden, oder liegen die Daten durch swapping im RAM? Aber wohl kaum komplett, oder? Oder ist eben das der Unterschied zw. usertime und systime?
      btw.2: werden Daten die auf einer Ramdisk liegen auch "geswappt"?

      Grüße
      Andreas

      1. Halihallo Andreas

        Ach, noch ein kleines Addone zur Aussage von Dir, Andreas:
        Ja, 15-20 Sekunden sind in der Tat sehr lahm, zumal das Durchsuchen von gleichen
        Datenmengen in der Selfsuche nur einen zwanzigstel davon brauchen.

        War nur so ein Gefühl, ich weiß nicht in wiefern man das vergleichen kann, so hat der Selfserver vermutlich mehr RAM als Du und erheblich schnellere SCSI-PLatten.

        beides wohl wahr.

        btw. Wie kann denn der Selfserver auf 0.8 Sekunden kommen? Vermutlich kommen die Daten per SCSI mit ca. 70 MB/sek, das wären dann mind. 3 Sekunden,

        Es müssen eben nicht alle Daten eingelesen werden. Die Daten liegen indiziert vor und
        wenn der Index gut ist, braucht man nur 5MB einzulesen. Darin besteht auch der Sinn des
        Index. Er ist nicht nur darauf optimiert, schnellstmöglich ein Eintrag zu selektieren,
        sondern ist sogar auf Fileebene dahingehend optimiert, dass möglichst wenige Lesezugriffe
        ausgeführt werden müssen.

        oder liegen die Daten durch swapping im RAM? Aber wohl kaum komplett, oder?

        Nun, komplett glaube ich weniger, es stehen ja "nur" 1GB zur Verfügung und es werden
        ja einige Prozesse ausgeführt.

        Oder ist eben das der Unterschied zw. usertime und systime?

        Als systime wird wohl die meisten Zeit für den HD-Zugriff/Socket verbraucht. Bei
        usertime geht es wohl um die Rechenleistung, die bei der DB anfällt. Die real
        verbrauchte Zeit ist die Summe beider. Glaube ich :-)

        btw.2: werden Daten die auf einer Ramdisk liegen auch "geswappt"?

        Hm. Was meinst du mit geswappt - auf die swap-partition ausgelagert? - Nun, dass wäre
        ja genau das, was u.a. verhindert werden soll? - Ich weiss nicht.

        Viele Grüsse

        Philipp