Глава.28 .Асинхронные.операции.ввода-вывода
вершении операции, а обращения к данным массива
Byte[]
внутри метода станут
безопасными.
рис. 28.2.
.Асинхронные.операции.ввода-вывода.в.Windows
Теперь, разобравшись с основами, посмотрим на открывающиеся перед нами
перспективы. Предположим, в ответ на клиентский запрос сервер выдает асин-
хронный запрос к базе данных. При этом наш поток не блокируется, а возвращается
в пул, получая возможность заняться обработкой других клиентских запросов.
Таким образом, получается, что для обработки
всех
входящих запросов достаточно
всего
одного
потока. Полученный от базы данных ответ также окажется в очереди
пула потоков, то есть наш поток сможет тут же его обработать и отправить данные
клиенту. Таким образом, единственный поток обрабатывает не только клиентские
запросы, но и все ответы базы данных. В итоге сервер практически не потребляет
системных ресурсов, но работает с максимально возможной скоростью, так как
переключения контекста не происходит!
Если элементы появляются в пуле быстрее, чем поток может их обработать,
пул может создать дополнительные потоки. Пул быстро создаст по одному по-
току на каждый процессор. Соответственно, на машине с четырьмя процессорами
четыре клиентских запроса к базе данных и ответа базы данных (в любой комби-
791
Операции.ввода-вывода.в.Windows
нации) будут обрабатываться в четырех потоках без какого-либо переключения
контекста
1
.
Однако при блокировке потока (выполнении синхронной операции ввода-вы-
вода, вызове метода
Thread.Sleep
или ожидании, связанном с блокировкой потока
в рамках синхронизации потоков) Windows уведомляет пул о том, что один из его
потоков прекратил работу. Пул для восполнения недостаточной загрузки процес-
сора создает новый поток взамен заблокированного. К сожалению, такой выход
из положения не идеален, потому что создание нового потока обходится довольно
дорого с точки зрения затрат времени и памяти.
Кроме того, позднее поток может быть разблокирован, и в итоге процессор
окажется перегруженным, что приведет к переключению контекста и снижению
производительности. Впрочем, эта проблема решается средствами пула. Завер-
шившим свою работу потокам, которые вернулись в пул, не дают обрабатывать
новые элементы, пока загрузка процессора не достигнет определенного уровня.
Таким способом уменьшается количество переключений контекста и повышается
производительность. Если впоследствии пул обнаружит, что потоков больше, чем
необходимо, он просто позволит лишним потокам самоуничтожиться, освободив
ресурсы.
Для реализации описанного поведения CLR-пул потоков использует такой
ресурс Windows, как
порт завершения ввода-вывода
(I/O Completion Port). Он
создается при инициализации CLR. Затем с этим портом можно связать подсо-
единяемые устройства, чтобы в результате их драйверы «знали», куда поставить в
очередь IRP-пакет. Подробнее этот механизм описан в моей книге «Windows via
C/C++» (Microsoft Press, 2007).
Асинхронный ввод-вывод кроме минимального использования ресурсов и умень-
шения количества переключений контекста предоставляет и другие преимущества.
Скажем, в начале сборки мусора CLR приостанавливает все потоки в процессе.
Получается, чем меньше у нас потоков, тем быстрее произойдет уборка мусора.
Кроме того, при уборке мусора CLR просматривает в поисках корней все стеки по-
токов. Соответственно, чем меньше у нас потоков, тем меньше стеков приходится
просматривать и тем быстрее работает уборщик мусора. Плюс ко всему, если в про-
цессе обработки потоки не были заблокированы, большую часть времени они будут
1
Предполагается, что другие потоки в это время отсутствуют. Большую часть времени
действительно так, ведь большинство компьютеров не задействует процессор на 100 %.
Однако даже при полной загрузке процессора все будет работать описанным образом, если
исполняемые потоки имеют низкие приоритеты. Наличие других потоков приводит к пере-
ключениям контекста. Это плохо с точки зрения производительности, но хорошо с точки
зрения надежности. Напоминаю, что Windows выделяет на каждый процесс по крайней
мере один поток и переключает контекст, гарантируя, что даже блокировка одного потока
не остановит работу приложения.
792
Do'stlaringiz bilan baham: |