2010-08-19 33 views
10

Mam plik xml, który należy czytać od wielu razy. Próbuję użyć Parallel.ForEach, aby przyspieszyć te procesy, ponieważ żaden z odczytanych danych nie ma znaczenia, w jakiej kolejności jest czytany. Dane są właśnie używane do wypełniania obiektów. Mój problem polega na tym, że otwieram plik za każdym razem w wątku jako przeczytany, tylko dlatego, że jest otwarty przez inny program. (Nie mam go otwartego w edytorze tekstów ani nic takiego :))Wiele wątków czytających z tego samego pliku

Jak mogę dokonać wielu odczytów z tego samego pliku?

EDYTOWANIE: plik jest ~ 18KB całkiem mały. Jest czytany od około 1800 razy.

Dzięki

+4

Twój twardy dysk ma tylko jedną głowicę, więc możesz czytać tylko jedną czytaną w tym samym czasie. Jakiej poprawy wydajności oczekujesz od tego? – Daniel

+1

Doe plik pasuje do pamięci podręcznej dysku? Jeśli tak, to wiele odczytów będzie szybkie, w przeciwnym razie, jeśli plik jest wystarczająco mały, aby zmieścił się w pamięci, użyj zamiast tego pliku odwzorowanego w pamięci i odczytaj z niego. W przeciwnym razie twardy dysk będzie spędzał dużo czasu na rzucaniu, zamiast wykonywać sekwencyjne odczyty, a utracisz wydajność, a nie ją osiągniesz. – mdma

+1

Jedna głowa na dysku twardym? Jestem pewien, że nawet dyski z pojedynczym talerzem mają teraz wiele głów, a także pamięć podręczną itp., Które ograniczają konkretne spowolnienia. – GrayWizardx

Odpowiedz

24

Jeśli chcesz wiele wątków odczytu z tego samego pliku, należy określić FileShare.Read:

using (var stream = File.Open("theFile.xml", FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    ... 
} 

Jednak nie osiągnie żadnego przyspieszenie od tego, dla wielu powodów:

  1. Twój dysk twardy może czytać tylko jedną rzecz na raz. Chociaż masz wiele wątków uruchomionych w tym samym czasie, wszystkie te wątki będą czekały na siebie nawzajem.
  2. Nie można łatwo przetworzyć części pliku XML. Zazwyczaj będziesz musiał przeanalizować cały plik XML za każdym razem. Ponieważ wiele wątków czyta go cały czas, wydaje się, że nie spodziewasz się, że plik się zmieni. Jeśli tak jest, to dlaczego musisz go przeczytać kilka razy?
+0

+1 Dla komentarzy "1" i "2". FileAccess.Read i FileShare.Read NIE rozwiążą problemu, gdy wiele wątków próbuje odczytać ten sam plik. Tak więc, jak wspomniano w komentarzu "2", jeśli potrzebujemy go tylko przeczytać, możemy najpierw przeczytać go raz, a następnie dać "wykonaj przetwarzanie" dla wielu wątków. – Vytas999

+0

Jeśli chodzi o punkt 1, nie ma to zastosowania do takich tablic, które dla oprogramowania serwerowego byłyby łatwe do przewidzenia. – Matt

1

Po otwarciu pliku, należy określić FileShare.Read:

using (var stream = new FileStream("theFile.xml", FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    ... 
} 

ten sposób plik można otworzyć kilka razy do czytania

+4

, podczas gdy jest to poprawne, chyba że plakat dzieli plik na bloki, wątpliwe jest, aby jakiekolwiek rzeczywiste przyspieszenie wystąpiło przy użyciu wielu wątków. –

+3

@Mitch Wheat: indeed. Ale właśnie odpowiadam na pytanie OP, nie osądzając czy używanie wielu nitek to dobry pomysł;) –

+1

Naucz człowieka łowić i wszystko to ... –

3

W zależności od rozmiaru pliku a typ odczytów, które wykonujesz, może być szybszy, aby najpierw załadować plik do pamięci, a następnie umożliwić dostęp do niego bezpośrednio do wątków.

Nie podałeś żadnych szczegółów na temat pliku, odczytów itp., Więc nie mogę powiedzieć na pewno, czy spełniałby on twoje specyficzne potrzeby.

Ogólną przesłanką byłoby załadowanie pliku raz w jednym wątku, a następnie bezpośrednio (poprzez strukturę Xml) lub pośrednio (przez XmlNodes, itp.) Zapewnić dostęp do pliku do każdego z wątków. I wyobrazić sobie coś podobnego do:

  1. załadować plik
  2. Dla każdego wysłania zapytania XPath węzły pasujące do gwintów.

Jeśli nici nie modyfikują bezpośrednio XML, może to być opłacalna alternatywa.

+0

Spróbuję załadować to do pamięci, dzięki za pomysł. – Pieces

Powiązane problemy