2009-08-20 11 views
2

Ich muss kleine Datensequenzen aus einer 3,7-GB-Datei lesen. Die Positionen, die ich lesen muss, sind nicht neben, aber ich kann die IO bestellen, so dass die Datei von Anfang bis Ende gelesen wird.So nutzen Sie die Disk IO-Warteschlangenfunktion

Die Datei wird auf einem iSCSI-SAN gespeichert, der in der Lage sein sollte, in der Warteschlange befindliche E/A zu verarbeiten/zu optimieren.

Die Frage ist, wie kann ich eine One-Shot-Anfrage von allen Daten/Positionen machen, die ich auf einmal brauche? Ist es möglich? Ich glaube nicht, async IO ist eine Option, da die liest sind sehr klein (20-200 Bytes)

Zur Zeit der Code sieht wie folgt aus:

using (var fileStream = new FileStream(dataStorePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    for (int i = 0; i < internalIds.Count();i++) 
    { 
     fileStream.Position = seekPositions[i].SeekPosition; 
     ... = Serializer.DeserializeWithLengthPrefix<...>(fileStream, PrefixStyle.Base128); 

    } 
    ... 
} 

Ich bin auf der Suche nach Möglichkeiten, dieses Ich zu verbessern/O weil ich etwas unterdurchschnittliche Leseleistung bekomme. All die Suchzeiten, die sich aus dem Bewegen des Kopfes ergeben, scheinen sich zu addieren.

Antwort

1

Haben Sie Performance Monitor (von Microsoft Sysinternals) auf diesem ausgeführt?

Ich bin mir nicht sicher, was das Problem ist, aber ich nehme eine Vermutung. Wenn Sie von einem SAN lesen, denke ich, dass Festplattenzugriffe zu Netzwerkanforderungen führen. Der erste Lesevorgang sendet eine Anforderung zum Suchen, Lesen und Puffern von Daten. Anschließend erstellt der Serializer die Objekte. Zu dem Zeitpunkt, zu dem Ihre zweite Anfrage gesendet wird, haben sich die SAN-Festplatten weiter gedreht, so dass Sie warten müssen, bis die Daten an Ort und Stelle sind.

Haben Sie Multithreading probiert? Ich bin neugierig auf die Leistung, wenn Sie eine Warteschlange von Dateiabschnitten einrichten, die Sie in sequentieller Reihenfolge verarbeiten müssen, ein paar Threads hochfahren, sie die Datei separat öffnen (FileSharing.Read, damit alle auf die Datei zugreifen können) und dann lass sie anfangen, Arbeit von der Warteschlange zu ergreifen. Ausgabe der Ergebnisse in eine andere Sammlung. Wenn die Reihenfolge für die Ausgabe von Bedeutung ist, sortieren Sie die Ausgabe nach der ursprünglichen Reihenfolge, in der Sie sie in die Warteschlange gestellt haben.

--- EDIT ---

Haben Sie versucht, die ReadFileScatter API? Here's a P-invoke signature from pinvoke.net.

+0

+1 für das Verständnis der Frage. Ich glaube, das ist genau das, was passiert ist, durch die Zeit, die zweite Lese getan werden muss, haben die Platten bereits gesponnene, also warum ich in eine Art und Weise bin auf der Suche Hardware-Warteschlangen zu tun. – andreialecu

+0

Ich hätte gedacht, dass Windows Hardware-Warteschlangen für Sie behandelt. Mit der Festplatte auf Base C# kann man sicher nicht mittelalterlich werden. Sie können nur sagen "Geh hierher und lese X Bytes". Ich würde mit verschiedenen Zugriffsmustern mit mehreren Threads experimentieren.Vielleicht wäre es schneller, wenn 2 Threads A und B lesen, dann C und D; oder vielleicht A und M, dann B und N. –

+0

Die ReadFileScatter API klingt vielversprechend. Ich habe meiner Antwort einen Klappentext hinzugefügt. –

0

Erstellen Sie einen einzigen Hintergrund-Thread als Disk-Proxy. Senden Sie alle Ihre Leseoperationen an sie, und sortieren Sie sie und führen Sie die Lesevorgänge zusammen. Wenn zwei oder mehr Regionen in der Nähe sind, lesen Sie den gesamten Sektor, der sie enthält, und nehmen Sie Teilabschnitte der Daten. Geben Sie die Daten asynchron zurück.

+0

Die Lesevorgänge sind bereits geordnet, und FileStream selbst führt diese Art der Pufferung bereits standardmäßig durch - Grund, warum die Leistung nicht ganz schrecklich ist. Finden Sie den folgenden Link für die Bestätigung, dass Pufferung tatsächlich passiert: http://blogs.msdn.com/brada/archive/2004/04/15/114329.aspx – andreialecu

0

Nur für das Protokoll:

In POSIX-Umgebungen Sie mehrere Bereiche eine Datei mit einem (SYS) Anruf mit der readv Funktion anfordern könnten. Eine weitere Möglichkeit in einer POSIX-Umgebung wäre eine nicht blockierende IO.