我该如何找到一个 .net 类是否使用了 IOCP?

23

更新

我问错了问题,根据回答和评论中的信息重新表述:

是否有关于.NET的异步操作真正是异步的好资料,因此要么是IOCP,要么是异步(重叠)? 有没有快速的方法可以找出是否有几个类这样做呢?

不要盲目信任框架开发人员的示例

创建FileStream的自然起点是静态的File.Open()方法,其文档未提及所创建的FileStream的同步性! 它也不允许您提供FileOptions(用于指定神奇的FileOptions.Asynchronous标志)。

相反,FileStream是使用FileOptions.None创建的。 任何异步操作都由Stream基类的乐于助人的实现假装,它只是将相应的同步方法包装在委托中,并使用BeginInvoke()方法在线程池上调用它。

这是与通常的“成功之坑”的设计哲学不同的地方,在该设计哲学中,.NET中的一切似乎都按照您的想法工作,而无需仔细阅读文档和/或逐渐发现隐蔽的陷阱。


我一直在尝试找到有关在.NET中使用IO完成端口的信息。

是否有好方法可以知道给定的.NET类是否正在使用IO完成端口? (而不必每次使用新类时运行某些测试。

我尝试了一些类和方法的msdn文档,但我找不到任何关于它的东西。

更好的是,如果有一些列表,其中包含使用IOCP的类的列表,那就更好了。


4
你是计划避免这样的类/方法吗?还是要接受它们?只要它们遵守合同义务,你通过了解它们能获得什么价值? - Damien_The_Unbeliever
1
拥抱。我之所以关注这个问题,是因为已经存在的设计具有自己的线程处理,并且没有使用 .net 的异步处理。当然,有各种争议闹得沸沸扬扬,但最主要的一个问题是调用 .net 的异步处理是否会涉及到线程方面类似的问题。IO完成端口改变了这一点。当然,真正的答案需要进行更详细的测量,并根据此设置概念证明并进行比较。代码的性能正在不断改进,但这是一个尚未探索的领域。 - eglasius
3
我不知道有任何情况(就像@usr的答案一样)下异步I/O API没有做到这一点。如果您发现在.NET框架中有一个 没有 使用这些API的I/O API,我期望它有一个很好的理由(尽管我承认可能没有记录在任何地方)。你需要做的是"提高层次"——相信框架开发人员已经"做了正确的事情",依赖于在那个层面上公开的抽象,并停止担心他们如何实现,使用更低级的原语即可。 - Damien_The_Unbeliever
3
@eglasius,BCL是我见过的最好设计的类库之一。每次发布时,他们必须对所有内容进行审核以确保正确性和可用性。我绝对相信他们能够做好这个基本的事情,比起我自己来说更加可靠。.NET经常用于高吞吐服务器,他们知道并测试和优化了这种情况。无线程IO在处理数千个同时请求方面是绝对必要的。 - usr
@usr 我完全同意,但我正在寻找一个可以引用的来源,证明这是 .net 中使用的设计准则。例如,在 MSDN 的 .net 异步模式文档中没有提到这一点,它们只关注适用于 IO 和 CPU 绑定 API 的一般模式。我明天会设置一个赏金来看看是否有帮助 :) - eglasius
显示剩余5条评论
2个回答

20
I/O完成端口是一个强大的平台实现细节,.NET不能盲目依赖其可用性。它将其留给CLR主机来实现操作系统支持的粘合剂。自.NET 2.0以来,基础托管接口为IHostIoCompletionManager

因此,如果您想要硬保证它们确实被使用,则需要获取您使用的CLR主机的源代码。这很难获得,有许多不同的主机,您需要申请微软工作才能访问资源。只有SSCLI20宿主可用于源代码,它已经过时,仅涵盖默认主机,而默认主机本身已进行了调整,以允许PAL提供I/O完成端口,但在您运行的真实CLR主机中肯定不存在。

您没有具体指明考虑哪些平台。一些猜测:

  • ASP.NET: 是的,I/O完成端口对于套接字非常重要
  • SQL Server: 很有可能,但并不是百分之百确定,它有以自己独特的方式处理事情的技巧
  • 桌面应用程序: 是的,适用于任何运行在NT分支上的.NET版本>=2.0
  • 紧凑版:绝对不行
  • 微型版:绝对不行
  • XBox:不太可能,操作系统的细节是个谜
  • Silverlight:Windows版本的CoreCLR.dll使用它,但没有ThreadPool.BindHandle
  • Phone7:与Silverlight类似
  • Phone8:大概率可以,但也是一个谜

需要强调的是,这些仅是基于经验的猜测,并没有证据支持。问题本身相当奇怪,如果你发现异步I/O是通过重叠I/O实现的,那么你也没有其他选择。


+1,这是很好的反馈,我没有考虑到平台在这个领域可能有差异。目标平台主要是asp.net和桌面(nt分支)。我的问题确实很奇怪,因为我一开始认为使用IOCP是真正异步I/O的唯一证明,但那不是唯一的选择。我正在寻找展示.NET使用真正IO异步的来源,以向那些认为在某个时候 buried on the implementation details .NET最终只使用一个线程的同行证明这一点。 - eglasius
@HansPassant,赏金怎么了?不应该是500吗?;-) - usr

18
通常,只有使用由Windows内核支持的异步IO实现的异步API才会被BCL提供。暴露不使用异步内核IO的异步方法将成为众所周知的异步-over-sync反模式,BCL设计人员肯定已经意识到了这一点。这不仅是无用的,而且对性能有害并且具有误导性。他们不会这样做。
Windows可以使用IOCP或使用常规重叠IO进行异步IO。两者都是高效的、异步的,因此比阻塞IO更可扩展。
所有这些都对您透明。信任异步真正是异步的,同步真正是同步的。
如果有疑问,请使用Reflector查看代码。每当我这样做时,我发现确认了我刚才所说的。我还没有见过一个偏离的例子。
通过Reflector可以看到,BCL调用相关Win32 API的异步版本。例如,我将检查文件和套接字:
- FileStream.BeginRead间接调用Win32Native.ReadFileNative,使用指向NativeOverlapped结构的指针。指针是通过调用Overlapped.Pack获得的。完成回调以这种方式存储。无法使用Reflector跟踪如何调用回调,因为该部分存在于CLR的本机部分中。我无法确定是否使用了IOCP,但我可以确定正在使用异步IO。 - Socket.BeginRead间接调用WSARecv。代码非常复杂。BCL似乎能够根据操作系统使用重叠IO和IOCP。检查在Socket.InitializeSockets中进行。决定使用哪种IO的变量存储在Socket.UseOverlappedIO中。如果该变量为false,则最终将调用Socket.BindToCompletionPort。
因此,对于套接字来说,现代操作系统上显然是IOCP。对于文件我无法确定。
我个人并不特别关心使用了什么类型的异步IO,只要它是非阻塞的。这是情况。

1
一般来说,你有支持这个观点的参考资料吗?我猜你所说的"async APIs"是指"async IO APIs"吧? - Peter Ritchie
1
严格来说,WinNT中并非所有的异步IO都是IOCP。您可以进行异步(重叠)操作,而无需将它们绑定到完成端口。但是+1,因为您所说的要点是正确的。 - Remus Rusanu
@PeterRitchie 这是我个人的参考,基于我的调查和推理。据我所知,没有任何官方资料支持这一说法。 - usr
@RemusRusanu 嗯,我不确定这一点,所以我说“通常情况下,它是IOCP”。我将该陈述更加明确了。 - usr
谢谢,你回答了正确的问题,而不是我最初写的内容。我希望有人能提供参考,但现在我知道应该寻找什么,或许可以找到一些资料 :) - eglasius
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接