2010-12-05 4 views
5

Kontext Wir haben eine selbst erstellte Dateisystem-unterstützte Caching-Bibliothek. Gegenwärtig haben wir aufgrund einer großen Anzahl von Einträgen (z. B. bis zu 100.000) Leistungsprobleme mit einer Installation. Das Problem: Wir speichern alle fs-Einträge in einem "Cache-Verzeichnis". Sehr große Verzeichnisse funktionieren schlecht.NTFS-Verzeichnis hat 100 K Einträge. Wie viel Leistungssteigerung, wenn über 100 Unterverzeichnisse verteilt?

Wir versuchen, diese Einträge über Unterverzeichnisse zu verteilen - wie Git tut, z. 100 Unterverzeichnisse mit je ~ 1000 Einträgen.

Die Frage

Ich verstehe, dass kleinere Verzeichnisse Größen mit Dateisystemzugriff helfen.

Aber wird die "Verbreitung in Unterverzeichnisse" beschleunigen durchqueren alle Einträge, z. Aufzählen/Lesen aller 100.000 Einträge? I.e. Wenn wir den Cache aus dem FS-Speicher initialisieren/aufwärmen, müssen wir alle 100.000 Einträge durchlaufen (und alte Einträge löschen) können mehr als 10 Minuten dauern.

Wird die "Datenspreizung" verringert, verringert sich diese "Traversierungszeit". Zusätzlich kann/"traversal" tatsächlich veraltete Einträge löschen (z. B. älter als N Tage). Werden "Daten verteilen" die Löschzeiten verbessern?

Zusätzlicher Kontext -NTFS -Windows Familie O (Server 2003, 2008)

-Java J2ee Anwendung.

Ich/wir würden uns freuen, wenn wir Probleme bei der Skalierbarkeit des Dateisystems haben.

Vielen Dank im Voraus.

wird

p.s. Ich sollte kommentieren, dass ich die Werkzeuge und die Fähigkeit habe, das selbst zu testen, aber ich dachte mir, dass ich zuerst den Schwarmgeist für die Theorie und Erfahrung auswählen würde.

+2

Haben Sie versucht, Dateisystem zu tunen?Zum Beispiel, kurze Dateinamen deaktivieren? –

Antwort

5

Ich glaubte auch, dass die Verbreitung von Dateien über Unterverzeichnisse Operationen beschleunigen wird.

Also habe ich die Tests durchgeführt: Ich habe Dateien von AAAA bis ZZZZ (26^4 Dateien, es ist etwa 450K) erstellt und sie in einem NTFS-Verzeichnis abgelegt. Ich habe auch die identischen Dateien in Unterverzeichnisse von AA bis ZZ platziert (d. H. Gruppierte Dateien nach den ersten 2 Buchstaben ihrer Namen). Dann führte ich einige Tests durch - Aufzählung und zufälliger Zugriff. Ich habe das System nach der Erstellung und zwischen den Tests neu gestartet.

Flache Struktur ausgesetzt etwas bessere Leistung als Unterverzeichnisse. Ich glaube, das liegt daran, dass die Verzeichnisse zwischengespeichert sind und NTFS Verzeichnisinhalte indexiert, so dass die Suche schnell ist.

Beachten Sie, dass die vollständige Aufzählung (in beiden Fällen) etwa 3 Minuten für 400 K-Dateien dauerte. Dies ist eine signifikante Zeit, aber Unterverzeichnisse machen es noch schlimmer.

Fazit: Besonders bei NTFS macht es keinen Sinn, Dateien in Unterverzeichnisse zu gruppieren, wenn der Zugriff auf diese Dateien möglich ist. Wenn Sie einen Cache haben, würde ich auch die Gruppierung der Dateien nach Datum oder nach Domäne testen, unter der Annahme, dass auf einige Dateien häufiger als andere zugegriffen wird, und das Betriebssystem nicht alle Verzeichnisse im Speicher behalten muss. Für Ihre Anzahl von Dateien (unter 100 K) würde dies jedoch wahrscheinlich auch keine wesentlichen Vorteile bieten. Sie müssen solche spezifischen Szenarien selbst messen, denke ich.

Update: Ich habe meinen Test für den wahlfreien Zugriff auf nur die Hälfte der Dateien (von AA auf OO) reduziert. Die Annahme war, dass es sich um ein flaches Verzeichnis und nur die Hälfte der Unterverzeichnisse handelt (was dem Unterverzeichnis case einen Bonus gibt). Das noch flache Verzeichnis schnitt besser ab. Also ich nehme an, dass, wenn Sie Millionen von Dateien haben, sie in einem flachen Verzeichnis auf NTFS halten wird schneller sein als Gruppierung sie in Unterverzeichnissen.

3

Wenn Sie nie das Cache - Verzeichnis auflisten oder auflisten müssen und nur Dateien darin anzeigen und öffnen, sollte es nicht wichtig sein (zumindest nicht auf der Ebene der 100k - Dateien), wie viele Dateien in der Verzeichnis.

Viele Caching-Frameworks und Dateisystem-schwere Storage-Engines erstellen Unterverzeichnisse basierend auf dem ersten Zeichen in den Dateinamen in solchen Szenarien, so dass, wenn Sie eine Datei "abcdefgh.png" in Ihrem Cache speichern, würde es " cache/a/b/cdefgh.png "statt nur" cache/abcdefgh.png ". Dies setzt voraus, dass die Verteilungen der ersten zwei Buchstaben Ihrer Dateinamen über den Zeichenraum ungefähr gleich sind.

Wie Sie bereits erwähnt haben, da Ihre primäre Aufgabe das Auflisten oder Durchlaufen der Verzeichnisse darin besteht, veraltete Dateien zu löschen, würde ich empfehlen, Verzeichnisse basierend auf dem Datum und/oder der Zeit zu erstellen, in dem die Datei zwischengespeichert wurde, zB "cache/2010 /12/04/22/abcdefgh.png "Wenn Sie den Cache indizieren, müssen Sie ihn nach dem Dateinamen und dem Datum indizieren (besonders wenn er in einer Datenbank gespeichert ist), sodass Sie Elemente nach Datum schnell aus dem Index entfernen und entfernen können das entsprechende Verzeichnis.

0

Wie laden Sie Ihren Cache? Wenn Sie Standard-Java-Dateisystem-Interaktion verwenden, wird das Ihr erster Engpass sein - Java ist ziemlich schlecht bei der Iteration von Ordnerinhalten - und wenn Sie während der Iteration Prüfungen für jede Datei durchführen (stellen Sie das Änderungsdatum her), vergewissern Sie sich, dass die Datei isn ist 't ein Verzeichnis, etc ...) Leistung kann einen großen Schlag (diese alle nehmen Rundreisen ins Heimatland). Der Wechsel zu einer Lösung, die auf nativem FindFirstFile basiert, kann erhebliche Verbesserungen (wie Größenordnungen) bewirken. FindFirstFile gibt bei jedem Iterationsschritt alle Informationen über die Datei zurück. Java File.listFiles() gibt die Liste der Pfade zurück. Dann, wenn Sie nach Attributen oder anderen Meta suchen - jeder Aufruf ist ein Rundgang zum Dateisystem. Schrecklich, furchtbar ineffizient.

OK - das ist aus dem Weg. Als nächstes ist die rohe Iteration eines großen Verzeichnisses in NTFS nicht besonders langsam als eine n-stufige Baummethode (Ordner und Unterordner usw.). Mit FAT32 war das eine sehr große Sache - aber NTFS behandelt diese Art von Sache ziemlich gut. Das Aufteilen in Unterordner eröffnet jedoch einige natürliche Parallelisierungsmöglichkeiten, die mit einem einzelnen Ordner viel schwieriger zu erreichen sind. Wenn Sie 10 oder 15 Threads spawnen können, die jeweils separate Ordner treffen, können Sie die Festplattenlatenz effektiv eliminieren.

Ich würde wahrscheinlich vorschlagen, dass Sie mit dem Profiling beginnen (das wussten Sie natürlich schon) - und sehen Sie, woher der Großteil der Ladezeit kommt. Sie werden vielleicht überrascht sein (zum Beispiel, in einer unserer Apps, die viele Dateilisten verarbeitet, war ich schockiert zu sehen, wie viel Zeit wir für die Überprüfung von isDirectory() bekommen haben - eine einfache Änderung wie das Vergleichen von vorher Verzeichnis/Datei-Bestimmung machte eine 30% ige Verbesserung unserer Iterationsgeschwindigkeiten).

0

Etwas zu sehen ist, wie Ihr Disk-Subsystem angeordnet ist. Während Platten schnell an Größe zunehmen, werden sie nicht viel schneller (in Zugriffszeit) ist eine andere Disk-Anordnung (mit mehr Festplatten) oder mit SSD-Laufwerke eine Option. Zum Beispiel hat eine SSD keine beweglichen Teile und kann 100K Dateien in 10 Sekunden berühren. Das Aufwärmen unnötig machen.

+0

"NTFS" nicht "NFS". Das Dateisystem ist lokal, nicht remote. – user331465

+0

@ user331465, ausgezeichneter Punkt. In diesem Fall schlage ich vor, dass Sie Ihre Hardware betrachten. Sie können nur so schnell gehen, wie sich die Laufwerke bewegen können. –