[linux-l] mbox/Maildir/tar
Rocco Rutte
pdmef at gmx.net
Mi Nov 28 20:00:46 CET 2007
Hi,
* Oliver Bandel wrote:
>Zitat von Rocco Rutte <pdmef at gmx.net>:
>> * Ivan F. Villanueva B. wrote:
>> >Am Mi, Nov 28, 2007 10:42:14 +0100, Rocco Rutte schrieb:
>> >> O(log(n))/O(1) statt O(n)
>> > ^^^^^
>> > das verstehe ich nicht
>> Gute Hashtabellen (max. 50% voll, gute Hashfunktion mit guter
>> Streuung)
>> haben im Mittel keine Kollisionen, d.h. der Eintrag ist nach
>> Berechnung
>> der Hashsumme modulo Tabellengröße immer im Mittel sofort gefunden.
>> Im
>> worst-case kommt die Komplexität glaube ich auf das Verfahren zur
>> Kollisionsauflösung an. Wenn man chaining (also verkettete Liste an
>> der
>> Stelle in der Tabelle) benutzt, kann man im schlechtesten Fall eine
>> einfach verlinkte Liste haben, also O(n) (z.B. wenn die Tabelle nur 1
>> Zeile hat). Bei linearem Auflösen (also Soll-Stelle je 1 Stelle
>> weiter
>> probieren) müsste man auch auf O(n) kommen. Für andere Verfahren
>> weiss
>> ich es nicht aus dem Kopf.
>[...]
>Was ich immer noch suche, ist die Antwort bzgl.
>der Listen. Du meintest irgendwas mit Listen auf dem baum drauf oder so?
>(Finde die Mail leider gerade nicht).
>Und ich frage mich, wo denn da Listen sind.
>Du schreibst hier was von hash; ich dachte es werden Bäume
>in den Dateissystenmen eingesetzt.
>Aber vielleicht wreden wir auch aneinander vorbei.
Ja. :)
Ivan hat gefragt warum Hashtabellen O(1) haben, und ich habe versucht
das zu erklären. Ich versuche mal die Verwirrung zu lösen...
Ein FS muss pro Verzeichnis wissen, welche Dateien sich darin befinden,
also Pointer zu den Metadaten. In meiner naiven Vorstellung ist das eine
einfache Liste im Trivialfall. Wenn man in einem Verzeichnis eine Datei
ändern will, dann erfolgt aus dem Userspace heraus der Zugriff über den
Pfad, d.h. das FS muss die Metadaten dazu erst suchen, also über die
Liste gehen, um die Infos der Datei zu finden (z.B. die Inode). Das
dauert lange wenn man viele Files hat.
Um das zu beschleunigen gibt es prinzipiell 2 Möglichkeiten: Baum oder
Hashtabelle. ext3 hat meines Wissens eine Abwandlung eines B+-Baumes,
UFS/FFS (BSD) haben IIRC eine Hashtabelle.
Und soweit ich mich richtig erinnere (bin zu faul zu gucken :), haben
B+-Bäume nur auf der untersten Ebene wirkliche Daten und einen weiteren
Pointer zum nächsten Kind des Elternknotens pro Blatt. Das ist dann
widerum eine einfach verlinkte Liste, wenn man nur das Leaflevel
betrachtet. "Darüber" ist dann ein B+-Baum für das schnelle Suchen in
der Liste.
Ab hier rate ich mal.
Für den Fall eines Baumes und Hashtabelle gibt es eine bestimmte
"Sortierung", in der readdir() die Dateien zurückliefert. Diese
Sortierung ist garantiert nicht nach Inode. Wenn man keinen Baum/Tabelle
hat, ist die Reihenfolge grob die der Erstellung (oder so, habe nie ein
FS geschrieben :) und damit IMHO der Abstand zwischen den Inodes zweier
readdir()-Ergebnisse im Mittel deutlich geringer als bei Baum/Tabelle.
Bei einem Baum oder eine Tabelle bekommt man bei readdir() allerdings
die Files in praktisch zufälliger Reihenfolge mit praktisch zufälliger
Inode.
D.h. in beiden letzteren Fällen sind die Inodes mit einer gewissen
Wahrscheinlichkeit durchschnittlich weiter auseinander als beim ersten.
Zumindest legen das meine einfachen Tests der letzten Tage (Optimierung
beim Lesen von großen Maildirs) nahe. Damit bringt es nach meinen Tests
bei derart "beschleunigten" Dateisystemen mehr oder minder wirklich viel
wenn man vorher nach Inode sortiert, wenn die Infos aus readdir() nicht
reichen (z.B. stat() oder open()).
Bis auf die Tests ist das nur geraten.
>> Nachteil: Hashtabellen brauchen viel Pflege
>[...]
>immer schön giessen ;-)
>Das Problem mit dem Suchen sieht da ja garnicht so schlimm aus.
>log(n) ist doch ganz nett.
>Deswegen denke ich auch, daß die Probleme von Maildir nicht
>daher rühren. Klar: je weniger man auf dem Filesystem herum rödeln
>muß, um so besser.
Ich habe keine harten Zahlen zu sowas, aber einmal den Kopf quer über
die Platte schieben kann mehrere stat() oder sogar open()+read()-Aufrufe
bedeuten, denke ich. Und wenn man das bei nahezu jedem stat() machen
muss, ist man X mal langsamer als wenn man es nur bei jedem 10. oder 20.
machen muss, weil man die ganze Zeit praktisch auf Kopfbewegungen warten
muss.
Der Faktor 12-13 bei mutt kommt wirklich nur durch Inode-Sortierung und
unter exakt den gleichen Bedingungen zu stande (gleiche Anzahl von
stat()/open() Aufrufen, die Kisten sind sonst idle), d.h. Schwankungen
bei I/O Wartezeiten kann man nahezu auscchließen. Zumindest wäre der
Faktor dann nicht so stabil.
Es gibt ein paar Mails auf lkml zum Sortieren und es gibt Sourcen für
readdir(), die via LD_PRELOAD das Sortieren übernehmen wenn man die
Anwendung sonst nicht anpassen kann.
Einfach mal zufällig 500k Files in einen Ordner werfern und messen wie
lange es dauert ein readdir() gefolgt von stat() auf jedes File zu
machen; und das ganze nochmal mit Inodes sortiert.
MfG, Rocco
Mehr Informationen über die Mailingliste linux-l