四种高性能服务器IO分析

上传人:油条 文档编号:13099840 上传时间:2017-09-04 格式:PDF 页数:32 大小:365.85KB
返回 下载 相关 举报
四种高性能服务器IO分析_第1页
第1页 / 共32页
四种高性能服务器IO分析_第2页
第2页 / 共32页
四种高性能服务器IO分析_第3页
第3页 / 共32页
四种高性能服务器IO分析_第4页
第4页 / 共32页
四种高性能服务器IO分析_第5页
第5页 / 共32页
点击查看更多>>
资源描述

《四种高性能服务器IO分析》由会员分享,可在线阅读,更多相关《四种高性能服务器IO分析(32页珍藏版)》请在金锄头文库上搜索。

1、异步 IO、 APC、 IO完成端口、线程池与高性能服务器之一 异步 IO 背景:轮询 PIO DMA 中断 早期 IO设备的速度与 CPU相比,还不是太悬殊。 CPU定时轮询一遍 IO设备,看看有无处理要求,有则加以处理,完成后返回继续工作。至今,软盘驱动器还保留着这种轮询工作方式。 随着 CPU性能的迅速提高,这种效率低下的工作方式浪费了大量的 CPU时间。因此,中断工作方式开始成为普遍采用的技术。这种技术使得 IO 设备在需要得到 服务时,能够产生一个硬件中断,迫使 CPU放弃目前的处理任务,进入特定的中 断服务过程,中断服务完成后,再继续原先的处理。这样一来, IO设备和 CPU 可以

2、同时进行处理,从而避免了 CPU 等待 IO完成。 早期数据的传输方式主要是 PIO(程控 IO)方式。通过对 IO地址编程方式的方式来传 输数据。比如串行口,软件每次往串行口上写一个字节数据,串口设备完成传输任务后,将会产生一个中断,然后软件再次重复直到全部数据发送完成。性能更好的 硬件设备提供一个 FIFO(先进先出缓冲部件),可以让软件一次传输更多的字节。 显然,使用 PIO方式对于高速 IO设备来说,还是占用了 太多的 CPU时间(因为需要通过 CPU编程控制传输)。而 DMA(直接内存访问)方式能够极大地减少 CPU处理时间。 CPU仅需告诉 DMA控制器数据块的 起始地址和大小,以

3、后 DMA控制器就可以自行在内存和设备之间传输数据,其间 CPU可以处理其他任务。数据传输完毕后将会产生一个中断。 同步文件 IO和异步文件 IO 下面摘抄于 MSDN synchronous file I/O and asynchronous file I/O。 有两种类型的文件 IO 同步:同步文件 IO和异步文件 IO。异步文件 IO也就是重叠 IO。 在同步文件 IO中,线程启动一个 IO操作然后就立即进入等待状态,直到 IO操作完成后才醒来继续执行。而异步文件 IO方式中,线程发送一个 IO请求到内核,然后继续处理其他的事情,内核完成 IO请求后,将会通知线程 IO操作完成了。 如果

4、 IO请求需要大量时间执行的话,异步文件 IO方式可以显著提高效率,因为在 线程等待的这段时间内, CPU将会调度其他线程进行执行,如果没有其他线程 需要执行的话,这段时间将会浪费掉(可能会调度操作系统的零页线程)。如果 IO请求操作很快,用异步 IO方式反而还低效,还不如用同步 IO方式。 同步 IO在同一时刻只允许一个 IO操作,也就是说对于同一个文件句柄的 IO操作是序列化的,即使使用两个线程也不能同时对同一个文件句柄同时发出读写操作。重叠 IO 允许一个或多个线程同时发出 IO请求。 异步 IO在请求完成时,通过将文件句柄设为有信号状态来通知应用程序,或者应用程序通过 GetOverl

5、appedResult察看 IO请求是否完成,也可以通过一个事件对象来通知应用程序。 异步 IO、 APC、 IO完成端口、线程池与高性能服务器之二 APC Alertable IO(告警 IO)提供了更有效的异步通知形式。 ReadFileEx / WriteFileEx在发出 IO 请求的同时,提供一个回调函数( APC过程),当 IO请求完成后,一旦线程进入可告警状态,回调函数将会执行。 以下五个函数能够使线程进入告警状态: SleepEx WaitForSingleObjectEx WaitForMultipleObjectsEx SignalObjectAndWait MsgWait

6、ForMultipleObjectsEx 线程进入告警状态时,内核将会检查线程的 APC队列,如果队列中有APC,将会按 FIFO方式依次执行。如果队列为空,线程将会挂起等待事件对象。以后的 某个时刻,一旦 APC进入队列,线程将会被唤醒执行 APC,同时等待函数返回 WAIT_IO_COMPLETION。 QueueUserAPC 可以用来人为投递 APC,只要目标线程处于 告警状态时,APC就能够得到执行。 使用告警 IO 的主要缺点是发出 IO请求的线程也必须是处理结果的线程,如果一个线程退出时还有未完成的 IO请求,那么应用程序将永远丢失 IO完成通知。然而以后我们将会看到 IO完成端

7、口没有这个限制。 下面的代码演示了 QueueUserAPC的用法。 /*/ /* APC Test. */ /*/ DWORD WINAPI WorkThread(PVOID pParam) HANDLE Event = (HANDLE)pParam; for(;) DWORD dwRet = WaitForSingleObjectEx(Event, INFINITE, TRUE); if(dwRet = WAIT_OBJECT_0) break; else if(dwRet = WAIT_IO_COMPLETION) printf(WAIT_IO_COMPLETIONn); return

8、0; VOID CALLBACK APCProc(DWORD dwParam) printf(%s, (PVOID)dwParam); void TestAPC(BOOL bFast) HANDLE QuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); HANDLE hThread = CreateThread(NULL, 0, WorkThread, (PVOID)QuitEvent, 0, NULL); Sleep(100); / Wait for WorkThread initialized. for(int i=5; i0; i-) Qu

9、eueUserAPC(APCProc, hThread, (DWORD)(PVOID)APC heren); if(!bFast) Sleep(1000); SetEvent(QuitEvent); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); 异步 IO、 APC、 IO完成端口、线程池与高性能服务器之三 IO完成端口 IO完成端口 下面摘抄于 MSDN I/O Completion Ports, smallfool 翻译,原文请参考 CSDN文档中心文章 I/O Completion Ports, http:/

10、。 I/O 完成端口是一种机制,通过这个机制,应用程序在启动时会首先创建一个线程池,然后该应用程序使用线程池处理异步 I/O 请求。这些线程被创建的唯一目的就是 用于处理 I/O 请求。对于处理大量并发异步 I/O请求的应用程序来说,相比于在 I/O请求发生时创建线程来说,使用完成端口 (s)它就可以做的更快且更有 效率。 CreateIoCompletionPort 函数会使一个 I/O完成端口与一个或多个文件句柄发生关联。当与一个完成端口相关的文件句柄 上启动的异步 I/O操作完成时,一个 I/O完成包就会进入到该完成端口的队列中。对于多个文件句柄来说,这种机制可以用来把多文件句柄的同步点

11、放在单个对 象中。(言下之意,如果我们需要对每个句柄文件进行同步,一般而言我们需要多个对象(如: Event来同步),而我们使用 IO Complete Port 来实现异步操作,我们可以同多个文件相关联,每当一个文件中的异步操作完成,就会把 一个 complete package放到队列中,这样我们就可以使用这个来完成所有文件句柄的同步) 调用 GetQueuedCompletionStatus 函数,某 个线程就会等待一个完成包进入到完成端口的队列中,而不是直接等待异步 I/O请求完成。线程(们)就会阻塞于它们的运行在完成端口(按照后进先出队列顺序 的被释放)。这就意味着当一个完成包进入到

12、完成端口的队列中时,系统会释放最近被阻塞在该完成端口的线程。 调用 GetQueuedCompletionStatus,线程就会将会与某个指定的完成端口建立联系,一直 延续其该线程的存在周期,或被指定了不同的完成端口,或者释放了与完成端口的联系。一个线程只能与最多不超过一个的完成端口发生联系。 完 成端口最重要的特性就是并发量。完成端口的并发量可以在创建该完成端口时指定。该并发量限制了与该完成端口相关联的可运行线程的数目。当与该完成端口相关 联的可运行线程的总数目达到了该并发量,系统就会阻塞任何与该完成端口相关联的后续线程的执行,直到与该完成端口相关联的可运行线程数目下降到小于该并发 量为止。

13、最有效的假想是发生在有完成包在队列中等待,而没有等待被满足,因为此时完成端口达到 了其并发量的极限。此时,一个正在运行中的线程调用 GetQueuedCompletionStatus 时,它就会立刻从队列中取走该完成包。这样就不存在着环境的切换,因为该处于运行中的线程就会连续不 断地从队列中取走完成包,而其他的线程就不能运行了。 对于并发量最好的挑选值就是您计算机中 CPU的数目。如果您的事务处理需要一个漫长的计算时间,一个比较大的并发量可以允许更多线程来运行。虽然完成每个事务处理需要花费更长的时间,但更多的事务可以同时被处理。对于应用程序来说,很容易通过测试并发量来获得最好的效果。 Post

14、QueuedCompletionStatus 函数允许应用程序可以针对自定义的专用 I/O完成包进行排队,而无需启动一个异步 I/O操作。这点对于通知外部事件的工作者线程来说很有用。 在没有更多的引用针对某个完成端口时,需要释放该完成端口。该完成端口句柄以及与该完成端口相关联的所有文件句柄都需要被释放。调用 CloseHandle 可以释放完成端口的句柄。 下面的代码利用 IO完成端口做了一个简单的线程池。 /*/ /* Test IOCompletePort. */ /*/ DWORD WINAPI IOCPWorkThread(PVOID pParam) HANDLE CompletePort = (HANDLE)pParam; PVOID UserParam; WORK_ITEM_PROC UserProc; LPOVERLAPPED pOverlapped; for(;) BOOL bRet = GetQueuedCompletionStatus( CompletePort, (LPDWORD)&UserParam, (LPDWORD)&UserProc, &pOverlapped, INFINITE); _ASSERT(bRet); if(UserProc = NULL) / Quit signal. break;

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号