Где/как я могу узнать, использует ли класс .net IOCP?
Обновление
Я задал неправильный вопрос, перефразировал (основываясь на большой информации об ответах и комментариях):
Есть ли хороший источник для асинхронных операций .net async, являющихся реальным async, таким образом, IOCP или async (overlapped)? Есть ли какой-нибудь быстрый способ узнать, делают ли это несколько классов?
Пример неверия разработчиков инфраструктуры вслепую
Естественной отправной точкой для создания FileStream является статический метод File.Open(), документация для которого ничего не говорит о синхронности созданного FileStream! Это также не позволяет вам предоставлять FileOptions (которые используются для указания волшебного флажка FileOptions.Asynchronous).
Вместо этого FileStream создается с помощью FileOptions.None. Любые асинхронные операции легко подделываются обязательной реализацией базового класса Stream, который просто переносит соответствующий синхронный метод в делегат и вызывает его в пуле потоков с использованием метода BeginInvoke().
Это отклонение от обычной философии дизайна "ямы успеха", где все в .NET, похоже, работает так, как вы думаете, без необходимости внимательно читать документацию и/или постепенно обнаруживать неясные уловы и gotchas с течением времени.
Я пытался найти информацию об использовании IO Completion Ports в .NET
.
Есть ли какой-либо хороший способ узнать, использует ли данный .NET-класс порты ввода-вывода IO? (без необходимости запускать некоторые тесты каждый раз, когда вы используете новый класс.
Я пробовал документы msdn для некоторых классов и методов, и я ничего не смог найти на нем.
Еще лучше, было бы, если бы там был список со списком классов с использованием IOCP.
Ответы
Ответ 1
Как правило, BCL предлагает только асинхронные API, если они реализованы с использованием async IO, поддерживаемых ядром Windows. Выявление методов async, которые не используют async kernel-IO, было бы известным анти-шаблоном async-over-sync, о котором наверняка знают дизайнеры BCL. Это было бы не только бесполезно, но и вредно для производительности и вводить в заблуждение. Они этого не делают.
Windows может выполнять асинхронное ввод-вывод с использованием IOCP или с использованием обычного перекрывающегося ввода-вывода. Оба они эффективны, асинхронны и поэтому более масштабируемы, чем блокировка IO.
Все это прозрачно для вас. Положитесь на async, чтобы быть действительно асинхронным, и синхронизация действительно синхронизирована.
Если есть сомнения, загляните под капот с помощью Reflector. Всякий раз, когда я это делал, я нашел подтверждение того, что я только что сказал. Мне еще предстоит увидеть отклоняющийся случай.
Что вы видите с Reflector, так это то, что BCL вызывает асинхронные версии соответствующих API Win32. В качестве примера я рассмотрю файлы и сокеты:
-
FileStream.BeginRead
косвенно вызывает Win32Native.ReadFileNative
с указателем на структуру NativeOverlapped
. Указатель получается путем вызова Overlapped.Pack
. Обратный вызов завершения сохраняется таким образом. Невозможно определить способ вызова обратного вызова с помощью Reflector, поскольку эта часть существует в нативной части CLR. Я не могу сказать, используется ли IOCP, но я могу сказать, что используется async IO.
-
Socket.BeginRead
косвенно вызывает WSARecv
. Код довольно сложный. BCL, похоже, может использовать перекрывающиеся IO, а также IOCP в зависимости от ОС. Проверка производится в Socket.InitializeSockets
. Решение о том, какое IO использовать, хранится в Socket.UseOverlappedIO
. Если эта переменная ложна, в конечном итоге вызывается Socket.BindToCompletionPort
.
Итак, для Sockets это явно IOCP на современных ОС. Для файлов я не могу сказать.
Мне лично не особо интересно, какой тип асинхронного ввода-вывода используется до тех пор, пока он не блокируется. Это так.
Ответ 2
Порт завершения ввода-вывода - это сильная деталь реализации платформы, которую .NET не может слепо зависеть от доступности. И это не так, он оставляет его для хоста CLR, чтобы реализовать клей для поддержки операционной системы для него. Основной интерфейс хостинга - IHostIoCompletionManager, доступный с .NET 2.0
Итак, если вы хотите получить твердую гарантию, что они действительно используются, вам нужно получить источник хоста CLR, который вы используете. Это трудно найти, их много, и вам нужно будет обратиться в Microsoft, чтобы получить доступ к источнику. В источнике доступен только хост SSCLI20, он устарел и охватывает только хост по умолчанию. Это было само по себе, чтобы позволить PAL предоставлять порт завершения ввода-вывода, безусловно, фактически не присутствовать в реальных хостах CLR, которые вы когда-либо выполняли.
Вы не были конкретно о том, какие платформы вы считаете. Некоторые факторы:
- ASP.NET: да, порты завершения ввода/вывода - большая часть для сокетов
- SQL Server: довольно вероятно, но не slamdunk, он имеет умение делать что-то по-другому.
- Рабочий стол: да, для любой версии .NET >= 2.0, которая работает на ветке NT
- Compact: определенно не
- Микро: определенно не
- XBox: маловероятно, детали ОС - большая тайна.
- Silverlight: версия Windows CoreCLR.dll использует его, но без ThreadPool.BindHandle
- Phone7: аналогично Silverlight
- Телефон8: большая тайна, возможно.
Подчеркивая, что это просто образованные догадки, которые не подкреплены доказательством. Вопрос в другом случае довольно странный, это не похоже на то, что у вас будет альтернатива, если вы узнаете, что асинхронный ввод-вывод был выполнен с перекрытием ввода-вывода.
Ответ 3
По моему опыту, следующие API на основе IOCP:
FileStream: BeginWrite/BeginRead. ПРИМЕЧАНИЕ. При создании FileStream вы должны передать FileOptions.Asynchronous
DNS: BeginGetHostByName/BeginResolve
Гнездо: BeginAccept/BeginConnect/BeginReceive и т.д.
WebRequest: BeginGetRequestStream/BeginGetResponse
SqlCommand: BeginExecuteReader/BeginExecuteNonQuery и т.д. Вы должны установить AsynchronousProcessing как true (по умолчанию это значение false).
WebServcie: BeginXXX в WebServiceProxy, сгенерированный WCF и InvokeAsync в ClientBase