2010-05-04 17 views
10

Rozumiem, dlaczego aplikacje sieciowe używałyby multipleksowania (aby nie tworzyć zbyt wielu wątków) i dlaczego programy używały połączeń asynchronicznych do potokowania (bardziej wydajne). Ale nie rozumiem celu wydajności AsynchronousFileChannel.Dlaczego warto używać AsynchronousFileChannel Java?

Wszelkie pomysły?

Odpowiedz

7

Jest to kanał, którego można używać do asynchronicznego odczytywania plików, tzn. Operacje we/wy są wykonywane w oddzielnym wątku, dzięki czemu wątek, z którego wywoływany użytkownik może wykonywać inne czynności, podczas operacji we/wy są wydarzenie. Na przykład: metody read() zwracają obiekt Future, aby uzyskać wynik odczytu danych z pliku. Możesz więc zadzwonić pod numer read(), który natychmiast powróci z obiektem Future. W tle kolejny wątek odczyta rzeczywiste dane z pliku. Własny wątek może nadal wykonywać pewne czynności, a gdy wymaga odczytanych danych, należy wywołać obiekt get() na obiekcie Future. To spowoduje zwrócenie danych (jeśli wątek tła nie zakończy odczytu danych, utworzy blok wątku, aż dane będą gotowe). Zaletą tego jest to, że twój wątek nie musi czekać na całą długość operacji odczytu; może zrobić kilka innych rzeczy, dopóki naprawdę nie potrzebuje danych.

Zobacz the documentation.

Należy pamiętać, że AsynchronousFileChannel będzie nową klasą w Java SE 7, która nie została jeszcze wydana.

+0

Dzięki, ale zastanawiałem się więcej o przyczynach efektywności - Nie mogę zrozumieć, dlaczego wykonanie I/O w innym wątku pomaga. Jeden wątek zawsze musi blokować wejścia/wyjścia, a nie ma zgłoszonego ponownego użycia zasobów, wykorzystania funkcji sprzętu ani żadnych innych zachowań zwiększających wydajność. –

+9

Zaletą tego jest to, że * nie * potrzebujesz dwóch wątków. Jeśli piszesz duże blob danych, na niskim poziomie, kontroler dysku wykonuje zadanie zapisywania danych na dysk przed sygnalizowaniem przerwania, które idzie w górę stosu, aby wywołać twój program obsługi zakończenia. Twój wątek nie musi blokować podczas tego procesu i może wykonywać inne czynności. Używasz jednego wątku mniej, program planujący wątek zarządza jednym wątkiem mniej, nie musisz używać powiadomień java. Zasadniczo zużywasz mniej zasobów, aby zrobić to samo. – lenkite

+2

System operacyjny może także zoptymalizować kolejność wykonywania asynchronicznych operacji we/wy. Na przykład, jeśli masz dużą liczbę odczytów z różnych regionów w pliku, które są wykonywane asynchronicznie, system operacyjny może je grupować w sekwencyjne odczyty, bez martwienia się o wykonanie wszystkich operacji w podanej dokładnej kolejności. –

3

Właśnie natknąłem się na inny, nieco nieoczekiwany powód użycia AsynchronousFileChannel. Podczas wykonywania losowych rekordów zapisu w dużych plikach (przekraczających pamięć fizyczną, dzięki czemu buforowanie nie pomaga we wszystkim) w systemie NTFS, okazuje się, że AsynchronousFileChannel wykonuje ponad dwukrotnie więcej operacji w trybie jednowątkowym w porównaniu do zwykłego FileChannel.

Moje najlepsze przypuszczenie jest takie, że ponieważ asynchroniczne Io sprowadza się do nałożonego IO w Windows 7, sterownik systemu plików NTFS może szybciej aktualizować swoje wewnętrzne struktury, gdy nie musi tworzyć punktu synchronizacji po każdym wywołaniu .

I mikro-porównania z RandomAccessFile aby zobaczyć, jak to wykonać (wyniki są bardzo zbliżone do FileChannel, a jeszcze połowa wykonywaniu AsynchronousFileChannel.

Nie wiem, co się dzieje z wielowątkowy pisze. Jest on Java 7, na dysku SSD (dysk SSD jest o rząd wielkości szybszy niż magnetyczny, a kolejna o wiele szybsza w przypadku mniejszych plików mieszczących się w pamięci).

Ciekawe, czy te same współczynniki utrzymują się w systemie Linux.

+0

Rzeczywiście, tak długo, jak twoje pliki są krótkie, aby zmieścić pamięć podręczną systemu operacyjnego, operacje wejścia/wyjścia kończą się natychmiast, niezależnie od tego, czy twoje operacje we/wy są synchroniczne, czy też nie. Dodam tylko, że otrzymasz 2x speedup max, gdy twoje I/O i obliczenia będą miały porównywalną długość. Jeśli obliczenie to tylko niewielki ułamek czasu we/wy lub we/wy jest nieznacznie krótszy od obliczeń, to nakładanie się ich również nie ma sensu. – Val

3

Głównym powodem, dla którego mogę myśleć o użyciu asynchronicznego IO jest lepsze wykorzystaj procesor. Wyobraź sobie, że masz jakąś aplikację, która przetwarza jakiś plik. Załóżmy również, że możesz przetwarzać dane zawarte w pliku w porcjach. Jeśli nie wykorzystasz asynchronicznego IO, aplikacja prawdopodobnie zachowa się w następujący sposób:

  1. Przeczytaj blok danych. Brak wykorzystania procesora w tym momencie, ponieważ jesteś zablokowany, czekając na odczyt danych.
  2. przetwarzać właśnie przeczytane dane. W tym momencie aplikacja zacznie zużywać cykle procesora podczas przetwarzania danych.
  3. Jeśli masz więcej danych do przeczytania, goto nr 1.

Wykorzystanie procesora wzrośnie, a następnie wyzeruje, a następnie wzrośnie, a następnie wyzeruje .... Idealnie nie chcesz być bezczynny, jeśli chcesz, aby aplikacja była wydajna i przetwarzała dane tak szybko, jak to możliwe. Lepszym rozwiązaniem byłoby:

  1. Issue asynchroniczny czytać
  2. Po zakończeniu odczytu następny problem asynchroniczny czytać, a następnie dane procesowe

Pierwszym krokiem jest ładującego. Nie masz jeszcze danych, więc musisz wydać odczyt. Od tego momentu, gdy otrzymasz powiadomienie, które zakończyło się po przeczytaniu, wydajesz kolejny asynchroniczny odczyt, a następnie przetwarzasz dane. Zaletą jest to, że do czasu zakończenia przetwarzania fragmentu danych prawdopodobnie zakończy się kolejny odczyt, więc zawsze masz dane do przetworzenia i dzięki temu wydajniej korzystasz z procesora. Jeśli przetwarzanie zakończy się przed zakończeniem odczytu, może być konieczne wydanie wielu asynchronicznych odczytów, aby mieć więcej danych do przetworzenia.

Nick

0

Oto coś nikt nie wspomniał: FileChannel, ponieważ realizuje InterruptibleChannel, a także wszystko, co ją wykorzystywać takie jak OutputStream zwróconej przez Files.newOutputStream() ma niefortunne [1] [2] własność że jakakolwiek operacja blokowania, którą wykonuje (np. read() i write()) z wątku, który jest w interrupted state, sam się zamknie z Channel z .

W przypadku miejsc, w których występuje taki problem, zamiast tego można użyć rozwiązania AsynchronousFileChannel.

Powiązane problemy