Frage

Ich baue eine Spielzeug-Datenbank in C # mehr über Compiler, Optimierer und Indizierungstechnologie zu erfahren.

Ich möchte zwischen (mindestens lesen) -Anforderungen maximale Parallelität halten für die Seiten in den Pufferpool zu bringen, aber ich bin verwirrt darüber, wie dies am besten in .NET zu erreichen.

Hier sind einige Möglichkeiten und die Probleme, die ich mit jedem kam über haben:

  1. Mit System.IO.FileStream und der BeginRead Methode

    Aber die Position in der Datei ist kein Argument BeginRead, ist es eine Eigenschaft der FileStream (über das Seek Verfahren eingestellt), so kann ich nur eine Anforderung zu einem Zeitpunkt ausgeben und habe den Strom zu sperren, für die Dauer. (Oder muss ich? Die Dokumentation ist unklar, was passieren würde, wenn ich die Sperre nur zwischen den Seek und BeginRead Anrufe gehalten, aber veröffentlichte es vor EndRead aufrufen. Wer weiß?) Ich weiß, wie dies zu tun, ich bin nur nicht sicher, es ist der beste Weg.

  2. Es scheint eine andere Art und Weise zu sein, zentriert um die System.Threading.Overlapped Struktur und P \ Invoke auf die ReadFileEx Funktion in kernel32.dll.

    Leider gibt es einen Mangel an Proben, vor allem in verwalteten Sprachen. Diese Strecke (wenn es gemacht werden kann, überhaupt arbeiten) anscheinend beinhaltet auch die ThreadPool.BindHandle Verfahren und die IO-Abschlussthreads in dem Threadpool. Ich habe den Eindruck, dass dies die Art und Weise sanktioniert ist mit diesem Szenario unter Windows umzugehen, aber ich verstehe es nicht, und ich kann nicht über einen Zugang zu der Dokumentation, die den Uneingeweihten hilfreich ist.

  3. Etwas anderes?

  4. In einem Kommentar, schlägt jacob ein neues FileStream für jeden im Flug lesen zu schaffen.

  5. Lesen Sie die gesamte Datei in den Speicher.

    Das würde funktionieren, wenn die Datenbank klein ist. Die Code-Basis ist klein, und es gibt viele andere Ineffizienzen, aber die Datenbank selbst nicht. Ich will auch sicher sein, ich die ganze Buchhaltung mache benötigt, um mit einer großen Datenbank umgehen (was ein großer Teil der Komplexität erweist: Paging, externe Sortierung, ...) und ich mache mir Sorgen, es könnte auch sein, leicht versehentlich zu betrügen.

Bearbeiten

Klärung der Grund, warum ich mit Lösung verdächtig bin 1: eine einzige Sperre den ganzen Weg von Beginread halten zu EndRead bedeutet, ich brauche jemanden zu blockieren, die eine nur lesen will initiieren, weil ein anderer Lese im Gange ist. Das fühlt sich falsch, weil der Thread die neue Lese initiieren könnte in der Lage sein (im Allgemeinen) etwas mehr Arbeit zu tun, bevor die Ergebnisse verfügbar sind. (Eigentlich nur das Schreiben hat mich dazu gebracht, eine neue Lösung zu denken, ich als eine neue Antwort setzen.)

War es hilfreich?

Lösung

Was wir taten, war eine kleine Schicht um I / O Completion Ports, ReadFile- und GetQueuedCompletion Status in C ++ / CLI zu schreiben, und dann zurück in C # aufrufen, wenn der Vorgang abgeschlossen. Wir wählten diese Route über Beginread und die C # async Betriebsmuster mehr Kontrolle über die Puffer verwendet, bereitzustellen, aus der Datei (oder Buchse) zu lesen. Das war ein ziemlich großer Leistungszuwachs über den rein verwalteten Ansatz, der mit jeder Lese neuen byte [] auf das Heap reserviert.

Darüber hinaus gibt es viel mehr komplette C ++ Beispiele für die Verwendung IO Completion Ports heraus auf dem interwebs

Andere Tipps

Ich bin mir nicht sicher, ob ich sehen, warum die Option 1 würde nicht für Sie arbeiten. Beachten Sie, dass Sie nicht zwei verschiedene Threads haben versucht, das gleiche Filestream zur gleichen Zeit nutzen - so werden Sie auf jeden Fall Probleme verursachen. Beginread / EndRead sollte Ihren Code lassen weiterhin ausführen, während der potentiell teure IO-Betrieb Orte nimmt, nicht irgendeine Art von Multi-Thread-Zugriff auf eine Datei zu aktivieren.

Also ich würde vorschlagen, dass Sie suchen und dann eine Beginread tun.

Was passiert, wenn Sie die Ressource (Dateidaten oder was auch immer) in den Speicher zuerst geladen und teilte es dann über Threads? Da es sich um eine kleine db. -. Sie werden nicht so viele Probleme haben, zu behandeln

Verwenden Ansatz # 1, und

  1. Wenn eine Anfrage kommt, nehmen Sperre A. Verwenden Sie es eine Warteschlange von anstehenden Leseanforderungen zu schützen. Fügen Sie es zu der Warteschlange und zurück einige neue Asynchron-Ergebnis. Wenn dies in der ersten Zugabe zu der Warteschlange ergibt, ruft Schritt 2 vor der Rückkehr. Entriegelungsschloss A vor der Rückkehr.

  2. Wenn ein Lese abgeschlossen (oder Schritt 1 genannt), nehmen Sie Sperre A. Verwenden Sie es knallen eine Leseanforderung aus der Warteschlange zu schützen. Nehmen Sie sperren B. Benutzen sie die Seek zu schützen -> BeginRead -> EndRead Sequenz. Entriegelungsschloss B. Update des Asynchron-Ergebnis von Schritt 1 erstellt haben, um diesen Vorgang zu lesen. (Da ein Lesevorgang abgeschlossen ist, rufen Sie diese erneut.)

Das löst das Problem der nicht-Thread blockiert, die eine Lese beginnt, nur weil eine andere Lese im Gange ist, aber immer noch Sequenzen liest, so dass die aktuelle Position des Dateistrom nicht durcheinander gerät.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top