天生.NET

以爱国的方式崩溃

统计

常用链接

阅读排行榜

评论排行榜

最新评论

嘿嘿,我是2011年的。LS,不会自己看前辈们的留言么?人家都贴了资料说了是IOCP了,哼。
10年来看,更加莫名其妙。 关于完成端口,我想说那么几句。 首先,我是从C++过来的,对完成端口情有独钟。 第二,看了这么多东西,讨论.net IOCP的。主要是这么几个问题? (1)、.net的异步是不是用的ICOP。 (2)、SocketAsyncEventArgs是不是IOCP? 从目前看来,至少SocketAsyncEventArgs要比.net异步选择要优秀一点。就拿它当ICOP用吧。 留个脚印。再留个邮箱,xd_huang1986@163.com。大家交流。欢迎2011年以后的哥们跟我讨论这个话题啊,^_^。
路过,留个记号:)
re: .NET平台下几种SOCKET模型的简要性能供参考 飞翔的青蛙脑袋 2009-01-27 10:54  
to 让变化成为计划的一部分

你贴那个网址打不开,需要用户和密码!

我在2009年来看这个,怎么有点时空穿梭的意味?
这么说来根本就没有什么意义!
很实用的工具,我也在用你的。
不过介简再放个回车键,空行的处理。
Sonic.net 在pause 时,也不能恢复.....
re: .NET平台下几种SOCKET模型的简要性能供参考 让变化成为计划的一部分 2006-06-30 18:22  
http://devauthority.com/blogs/krys/archive/2006/06/13/HighPerformanceSocket.aspx,
High Performance Socket in .NET - using IOCP Thread & more..

嘿嘿,就是用IOCP做的Socket。
Sonic.net 的问题比较严重,经常会发现,只有一个线程在那里狂转,其他的线程闲着。这个很不符合IOCP的原意。所以,Sonic.net 还只能算是试图模拟IOCP,但模拟的并不完美。
终于在这里找到异步是使用iocp的最后说法了,但是随之而来的一个问题是,为什么很多地方都说异步的性能比不上真正的iocp 呢?

另外这个c#下的一个iocp实现:
Sonic.net
http://www.codeproject.com/csharp/managediocp.asp
测试了一下,发现有一个比较严重的bug,就是在队列数大的时候,工作时间长了,就会发生只有一个线程在运行,而且线程处于等待的情况。在性能方面通过和使用api的GetQueuedCompletionStatus等iocp函数对比,也还是有点差距......

难道dotnet真的不可能达到iocp性能?
to 飞刀.Net:
其实这个帖子所讨论的问题可以从平台实现机制和网络I/O模式两方面来看,尽管在linux/win32下具体机制略为不同,各有局限,但依然存在着借助模式设计实现"跨平台完成端口"的可能,比如说ACE中的前摄器模式(proactor)。我想ACE就是你要找的东西。
我这几天安心看了一下完成端口方面的资料.

发现他的模型与Java中的nio差不多,应当nio的windows实现就是使用的完成端口.

我看了资料后发现,ThreadPool,Select在完成端口的实现中一个都没有少过,好像没有太新的东东(当然他上个世纪末就出现了),所以楼主对几种的分类,好像界限不对.

唯一的区别就是把用户态的线程调入了核心态,减少了可能的线程切换,更有利操作系统本身对CPU时间片的利用.

单就模型来说,在用户态中亦可实现,就像Sonic.Net一样以及java中的concurrent中线程池的实现.

其实楼上的争论似乎没有太大的意义,.Net中的线程似乎也是个本地线程(不像Java中是JVM的自身实现的线程),其本身的ThreadPool就更不用说了,而且Windows的线程本身就是可以调入核心态的.从理论上说,用.net实现的IOCP确实可以获是和Win32一样的性能,现实估计也差不了很多(Sonic.Net作者自己说的).

现在我想的问题的就是在Linux这样的一个分时系统之下,需要如何完成类似完成端口的东东,如何减少线程(进程)的切换?
ccBoy提供了一个aio,我不太清楚,我呆会儿查查.

不知道大过年的,有没有人还有兴趣和我讨论这些?
领教了:)

没想到这些日子来的疑惑今天都有了点头绪了。

性能上的问题,我最后也提到了,是一些资料的摘抄,我自己也没有试过。

但从原理和表层实现方式来上说,这些指标也是大概有个数的。

对于一般的程序设计,选择哪个模型也有一点意义的:)

这种方式你不能根据CPU控制线程池中线程数的多少,你也不能控制并发的隔离等级。

关键是大家知道原理和优劣了,不要拘泥于某个结论:)这么说来,天生这样上面的四种分类和大概性能需xxx的结论要调整调整或重新思考了

还要好好再学习和细细体会,真是学无止境啊,Sumtec列的文章也看过,但是对文章中提的CompletionPort完全没有印象

Ps: Sumtec , 你记忆力真好,而且有信心保持自己的观点,赞一个。
@ 所有人:

大家别忙活了,我的记忆还是没有什么大问题。刚才搜了一片文章,微软的够权威了,确实是用的IoCompletionPort(除非微软撒谎),前提是操作系统支持:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/progthrepool.asp

请大家注意下面这段话:
 
CompletionPortThreads
This kind of thread is used for I/O operations, whenever is possible. Windows NT, Windows 2000, and Windows XP offer an object specialized on asynchronous operations, called IOCompletionPort. With the API associated with this object we can launch asynchronous I/O operations managed with a thread pool by the system, in an efficient way and with few resources. However, Windows 95, Windows 98, and Windows Me have some limitations with asynchronous I/O operations. For example, IOCompletionPorts functionality is not offered and asynchronous operations on some devices, such as disks and mail slots, cannot be performed. Here you can see one of the greatest features of the .NET Framework: compile once and execute on multiple systems. Depending on the target platform, the .NET Framework will decide to use the IOCompletionPorts API or not, maximizing the performance and minimizing the resources.


If you run this program on Microsoft Windows NT, Windows 2000, or Windows XP, you will see the following output:

Connected to localhost:80
WorkerThreads: 24, CompletionPortThreads: 25
Request sent to localhost:80
WorkerThreads: 25, CompletionPortThreads: 24

As you can see, connecting with a socket uses a worker thread, while sending the data uses a CompletionPort. This following sequence is followed:

  1. We get the local IP address and connect to it asynchronously.
  2. Socket performs the asynchronous connection on a worker thread, since Windows IOCompletionPorts cannot be used to establish connections on sockets.
  3. Once the connection is established, the Socket class calls the specified function ConnectCallback. This callback shows the number of available threads on the pool, this way we can see that it is being executed on a worker thread.
  4. An asynchronous request is sent from the same function ConnectCallback. We use for this the BeginSend method, after encoding the Get / request in ASCII code.
  5. Send/receive operations on a socket can be performed asynchronously with an IOCompletionPort, so when our request is done, the callback function SendCallback is executed on a CompletionPortthread. We can check this because the function itself shows the number of available threads and we can see that only those corresponding to CompletionPorts have been decreased.
If we run the same code on a Windows 95, Windows 98, or Windows Me platform, the result will be the same on the connection, but the request will be sent on a worker thread, instead of a CompletionPort. The important thing you should learn about this is that the Socket class always uses the best available mechanism, so you can develop your application without taking into account the target platform.
 
 
各位,可以盖棺定论了吗?

Inside I/O completion ports
http://www.sysinternals.com/Information/IoCompletionPorts.html

其实IOCP对应到Linux平台就是Linux AIO,这个在Linux 2.5之后版本才完全支持,但好像还不完全支持socket,其实IOCP这种模式下相当于对应每一个客户请求使用一个系统的线程,并且使用异步IO的方式。这种方式下你的线程切换时间非常的少,几乎不切换。

@问 题 男:
哦,没有注意。受教了:)
不多说,只谈一点“有io completion不一定就是io completion ports(不是广义的,特指sdk中的概念)”

win32中ReadFileEx、WriteFileEx等api有一个参数是iocompletion routine,这个不是io completion ports,切不可混为一谈,ioc routine使用的是核心态apc+alertable io的技术。这个技术和其他异步io技术从执行效果看,和io completion ports差不多,都实现了异步,但是性能上存在着差距,拿ioc routine来说,它规定,只能在调用io api的线程中服务io完成后的工作,比如某线程调用了ReadFileEx(...callback),则这个callback函数的执行线程一定是调用ReadFileEx的那个,而且系统只会在线程处于alertable态时才调用callback,这就意味着在io实际完成时即使有n多空闲的线程,只要调用io的那个不处于alertable态,则callback便不会被调用,这显然是低效的。其他的诸如overlapped的异步技术也会受到这样那样的的限制。与这些不同的是,使用io completion ports模型则高效得多,一个port关联着许多io handle,也关联了一些服务线程,当某一线程调用了io api,在io完成时,任何关联到此port的线程都可以为这个io handle服务,系统核心选出(使用最近使用的)其中一个然后把控制权交给它。可见,使用iocp能尽量发挥系统中cpu的能力,不至于部分忙死,部分饿死。io completion ports的目的就是平衡使用所有cpu的能力

另外,io completion ports是核心对象,使用模拟方式实现的性能估计都达不到系统提供的,比如双鱼座兄提到的http://www.codeproject.com/csharp/managediocp.asp,不过.net如此实现将更具兼容性,且估计性能上差不了多少

应该说iocp也不总是高效的代名词,在单cpu系统中,他和其他一些异步技术不会有太大差别,原因很简单,即使开n多线程,在某一时刻也只能有一个线程占据cpu,多线程的好处体现不出多少,多线程的切换反而会加重系统的负担,于是iocp对于普通异步技术的优势也体现不出来了

前来领砖,各位多多赐予,表客气

btw:

@双鱼座:
“IOCP是Windows2000/NT特有的Socket模型”——iocp不仅仅可用于socket,一般的磁盘io也可使用

@sumtec:
此io completion非彼io completion ports,参看前述
不错的帖
我认为这篇文章不错,当然如果你只想用C#的话
http://www.theukwebdesigncompany.com/articles/iocp-thread-pooling.php

A good rule of thumb is to set the concurrency level to match the number of CPU’s in the system. If the machine our server is running on only has one CPU, then only one thread can be executing at any given time. It will require a task swap to have another thread get CPU time. We want to reduce the number of active threads at any given time to maximize performance. This also leads to scalability. As the number of CPU’s increase, we can increase the concurrency level because there is a CPU to execute that thread. This is a general rule and is always a good starting point for configuring our thread pools.
比较同意 双鱼座 这个说法
从命名上来得出结论说服力不强
Winsock中IO模型有五种,这些可以参考相关文档。
Overlap模型是异步Select模型的优化,是一个比IOCP兼容范围广(适宜所有的Windows版本),但性能比IOCP略逊的一种IO模型.与IOCP模型的共同点是工作者线程回调中处理机制相同,都需要通过Overlap结构来承载数据;区别在于,不会通过调用CreateIoCompletionPort建立端口,也不会调用GetQueuedCompletionStatus来轮询。
如果你没有找到所调用的那两个函数,就不能说明是否采用了IOCP。
刚查过了,确认.NET背后的机制就是IOCP(个人认为)。用Reflector看System.Threading.IOCompletionCallback的callee,可以看到这么一条调用链:

System.Threading.IOCompletionCallback
Depends On
Used By
System.Net.Sockets.OverlappedCache..ctor(Overlapped, Object, IOCompletionCallback, Boolean)
Depends On
Used By
System.Net.Sockets.BaseOverlappedAsyncResult.SetUnmanagedStructures(Object) : Void
Depends On
Used By
System.Net.Sockets.OverlappedAsyncResult.SetUnmanagedStructures(Byte[], Int32, Int32, SocketAddress, Boolean) : Void
Depends On
Used By
System.Net.Sockets.OverlappedAsyncResult.SetUnmanagedStructures(Byte[], Int32, Int32, SocketAddress, Boolean, OverlappedCache&) : Void
Depends On
Used By
System.Net.Sockets.Socket.DoBeginReceive(Byte[], Int32, Int32, SocketFlags, OverlappedAsyncResult) : SocketError
System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[], Int32, Int32, SocketFlags, EndPoint, SocketAddress, OverlappedAsyncResult) : Void
System.Net.Sockets.Socket.DoBeginSend(Byte[], Int32, Int32, SocketFlags, OverlappedAsyncResult) : SocketError
System.Net.Sockets.Socket.DoBeginSendTo(Byte[], Int32, Int32, SocketFlags, EndPoint, SocketAddress, OverlappedAsyncResult) : Void

说错了不要扔板砖啊,大过年的。
如果我没有记错的话,.NET里面的很多异步IO,背后都是用的IOCP的。也就是说,用BeginXXX/EndXXX实际上应该就是使用的IOCP。不太记得了,我要查一下。
Managed I/O Completion Ports这个我看过,我想应该算是伪IOCP
我没有找到.NET用IOCP来搞的Socket例子,真的很想见识一下。
性能方面,数值只是一个参考值,取决的因素很多,但MSDN上报的IOC-6000我不太清楚,我这里看过的单台游戏端服务器上万连接是常常的。



.net上的完成端口实现很多呀,在CodeProject上随便一搜就是一大把。例如那个Sonic.net好象比较有名:http://www.codeproject.com/csharp/managediocp.asp

不过你那个“大概性能:XXXX连接”是完全不可信的。影响最大可连接数的因素很多很多,例如:CPU个数、工作者线程回调复杂度、内存容量等等。当然,使用何种Socket模型也有关系,MSDN的文章说IOCP是最好的,文章上报出的也只是6000个连接(非托管)。

当然,都知道IOCP是Windows2000/NT特有的Socket模型(http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/default.aspx
),不具有广泛的兼容性,更别说Linux/Mono了。并且大部分情况下,托管代码都是通过AppServer(例如IIS)获取Socket服务端连接,自己写纯托管的Socket服务端好象没有多大必要。
我现在很关注这方面的动态.

.net的ThreadPool不是完成端口。
Socket + ThreadPool 和Socket + Asynchronous本质上是一样的,性能自然也没有什么差别。