2016-07-28 26 views
0

Ich habe eine Klasse, die Bilddaten aus großen Dateien mit FileStream Zeile für Zeile liest. Intern werden die Dateien in Stücke gebrochen, von denen jeder sieht wie folgt aus:Wird FileStream.Seek() mit SeekOrigin.Begin optimiert, wenn keine Suche erforderlich ist?

 
================= 
| Header  | 
================= 
| Data I Want | 
================= 
| Data I Ignore | 
================= 

Um eine Zeile von Daten zu lesen, ich berechnen, welche Brocken hat die Zeile ich will, Seek() an den entsprechenden Offset und las einen festen Anzahl der Bytes. Wenn ich mehrere Zeilen innerhalb eines einzelnen Chunks lese, könnte ich tatsächlich alle Seek() Aufrufe überspringen, aber die erste, weil der Zeiger schon ist, wo ich es nach einem Read() will. Aber ich muss Seek() beim Springen zu einem neuen Brocken. Der Einfachheit halber berechne ich immer den absoluten Offset der nächsten Zeile in der Datei und Seek() dazu unter Verwendung von SeekOrigin.Begin. Ist FileStream.Seek() (oder die zugrunde liegende SetFilePointer() native Funktion) optimiert, um zu erkennen, dass eine gegebene Suche ein No-Op ist? Wenn nicht, sollte ich wahrscheinlich meinen eigenen Code optimieren, da er nicht blitzschnell ist.

+1

_ "Es ist nicht blitzschnell" _ - Ich bezweifle, dass das etwas damit zu tun hat, wie oft man 'Seek()' nennt. Natürlich, ohne eine gute [mcve], die zuverlässig den aktuellen Stand des Codes und ein klar angegebenes Leistungsziel reproduziert, ist es nicht möglich, in irgendeiner nützlichen oder präzisen Weise zu diskutieren, was Sie im Hinblick auf die Optimierung brauchen oder nicht brauchen. Wenn Sie Wert auf Leistung legen und wissen möchten, wie sich verschiedene Implementierungen und/oder Optimierungen auf die Leistung auswirken, müssen Sie dies ** selbst testen **. Schreiben Sie den Code einfach so, wie Sie möchten, und vergleichen Sie die Ergebnisse. –

+0

Der Grund, warum ich die Frage gestellt habe, ist, dass ich die Arbeit bei der Optimierung der unnötigen 'Seek()' -Aufrufe überschätzt habe und gehofft hatte, dass irgendjemand nur von der Spitze wissen würde, dass Microsofts Code diese Optimierung bereits vorgenommen hat. Ich war besorgt über die Möglichkeit, dass aus Gründen, die ich nicht erraten könnte, die Suche mit SeekOrigin.Begin tatsächlich die HD benötigen würde, um den Anfang der Datei zu finden und sequenziell an den angegebenen Ort zu lesen. Ich wollte nur optimieren, wenn das stimmt. Aber am Ende war das Hinzufügen des Checks zu meinem Code einfacher als ich dachte, also fügte ich es hinzu. – adv12

+1

_ "Ich war besorgt über die Möglichkeit, dass ... Suche mit SeekOrigin.Begin würde die HD wirklich benötigen, um den Anfang der Datei zu finden und sequenziell an den angegebenen Ort zu lesen" _ - Ich habe den Windows-Code nicht gesehen, aber ich kann praktisch garantieren, dass das nicht der Fall ist. Ehrlich gesagt, könnte Ihr Versuch, dies zu "optimieren", zu einer _poorer_ Leistung geführt haben; Zumindest müssen Sie nun die Dateiposition separat verfolgen, oder schlimmer noch, Sie betrachten die Eigenschaft 'Position', die den gleichen Übergang von Benutzer zu Kern bewirkt wie' Seek() '. –

Antwort

1

Die Antwort scheint ja zu sein.

Das einzige Problem hier ist der Lesepuffer. Wir können annehmen, dass der zugrundeliegende SetFilePointer() Aufruf ein Nicht-Op für einen Suchvorgang ist.

Wenn Sie die source for Seek konsultieren, können Sie sehen, dass versucht wird, so viel wie möglich aus dem Lesepuffer zu erhalten.

+0

Der Code nicht vollständig ignorieren die Situation eines No op seek, aber es wird immer einen Kernel-Aufruf an die win32api ausführen, was wahrscheinlich der größte Nachteil ist, den die Seek-Methode haben kann (abgesehen von Stream Flushing, das irgendwann passieren würde) – Gilthans

+1

Es gibt natürlich einige Overheads, aber auch den Kernel-Aufruf wird unbedeutend sein im Vergleich zu jedem tatsächlichen IO. –

+1

Wenn das so ist, ist die Frage sinnlos. Offensichtlich, wenn kein IO von der HD benötigt wird, ist es egal, was der Code von .NET tatsächlich tut, da er kein IO benötigt. Ich glaube, was der OP wissen wollte, ist, wenn er Leistung erzielen kann, indem er die Suche auslässt, wenn es unnötig ist. – Gilthans

1

Wenn Sie einen Blick auf die FileStream.Seek Quellcode nehmen hier über: http://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs,329c77a859ac60bd

Sie, dass unabhängig von der alten Position des Dateizeigers sehen können, die SeekCore Methode aufgerufen wird, die sich die Win32Native ruft .SetFilePointer, das ist ein Kernel-Aufruf.

Also die Antwort ist nein, es ist nicht optimiert, und Sie sollten es selbst optimieren, wenn Sie können.

+0

Es ist nicht erforderlich, auf Websites von Drittanbietern für die .net-Quelle zu verweisen. [Microsoft bietet die Quelle online] (http://referencesource.microsoft.com/mscorlib/system/io/filestream.cs.html#329c77a859ac60bd) –

+0

Ich habe das erste Google-Ergebnis verwendet, aber es ist wahr, dass es besser ist zu verwenden Microsoft Originaldokumentation. Ich aktualisierte den Link – Gilthans

+2

Eine einfache Möglichkeit, dorthin zu gelangen, gehen Sie zu http://sourceof.net und es wird Sie umleiten zu http://referencesource.microsoft.com/ –