IP's von access_log in bestimmtem Zeitfenster extrahieren
Philipp Hasenfratz
- programmiertechnik
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
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
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.
- 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
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
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 :-)
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
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
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
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
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
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
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
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
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
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
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
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
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