异步IO性能探究[转]

异步IO性能探究[转]

一、异步IO
        对于应用程序而言,有两种类型的IO调用:即同步IO 与异步IO。其本质的区别是:同步IO会block当前的调用线程,而异步IO则允许发起IO请求的调用线程继续执行,等到IO请求被处理后,会通知调用 线程。在windows平台上,应用程序可以调用CreateFile API, 并通过设置FILE_FLAG_OVERLAPPED标志来决定是否发起异步IO请求。
        对于异步的IO请求,其最大的好处是:慢速的IO请求相对于应用程序而言是异步执行,这样可以极大提高应用程序的处理吞吐量。发起IO请求的应用程序需要关心的是IO执行完成的结果,而不必忙等IO请求执行的过程。
       事实上,无论对于同步IO,还是异步IO,当IO请求发送到device driver后,device driver的执行总是异步的,当它接到IO请求之后,总会马上返回给IO System。而IO System是否立即返回给调用线程,则取决于FILE_FLAG_OVERLAPPED标志的设置,如下图:

异步IO性能探究[转]_第1张图片
二、异步IO的同步问题。
        我们使用异步IO,是为了提高应用程序的处理吞吐量。但是,当异步IO不再异步时(无论你是否设置FILE_FLAG_OVERLAPPED标志),应用 程序的性能会受到极大的影响。根据Microsoft Knowledge Base 156932, 在下列几种情况下,异步IO会失去它的异步性,而表现出同步的性质:
1)如果文件使用了NTFS compression压缩,则system driver不会异步地存取这样的文件。
2)扩展文件长度的IO操作不会是异步操作。
3)Cache机制。如果IO操作使用了file system cache,则这样的IO操作会被当成同步IO,而非异步IO。
即使你使用了FILE_FLAG_OVERLAPPED标志。在这种情况下,
a.如果需要读取的数据已经在Cache里,那么I/O drivers会认为这样的IO请求可以被立即处理,其结果是ReadFile 或者WriteFile调用返回TRUE,表示是:同步处理完成。
b. 如果需要读取的数据不在Cache里,windows NT的file system是使用page-faulting机制来实现cache管理,而page-faulting总是被同步处理, Windows NT没有提供异步的page-faulting机制。的确, file system driver使用了线程池来缓解这一问题,但是,当应用程序发起的IO请求足够多时,线程池还是不能应付的。
        在我们开发基于异步IO应用程序时,应该避免上述问题的出现,因为它们会使程序的性能大打折扣。
那么,对于Cache,我们如何避免呢?答案是:请使用FILE_FLAG_NO_BUFFERING标志。这个标志会使异步IO真实地异步执行。
三、性能的测试数据(仅供参考)。
      我在我的机器上,简单地对使用FILE_FLAG_NO_BUFFERING标志的异步IO,与不使用FILE_FLAG_NO_BUFFERING标志的异步IO进行了对比。
操作:顺序读取1G的文件。
x轴表示:每次读取的字节数(单位:K/每次)
Y轴表示:读取完成所需要的时间。(单位:millisecond)
注意:每次测试读取的内容总数是相等的(1000M)。
例如:如果每次读取128k,则需要读取8000次(128k*8000 = 1000M)。
如果每次读取256k,则需要读取4000次(256k*4000 = 1000M)。
粉红色的线没有使用FILE_FLAG_NO_BUFFERING标志,而黄色的线使用了FILE_FLAG_NO_BUFFERING标志。

异步IO性能探究[转]_第2张图片

从以上的数据,我们可以得出以下结论:
1) 当使用FILE_FLAG_NO_BUFFERING标志,应用程序的性能会极大提高,大概有50%的提高。
2) 在使用异步IO的时候,还有一个注意的问题是:当你每次读取的字节数增大的时候,性能也会提高。尤其在小于1024k时,当增大次读取的字节数,性能都有 明显的提高。在混合了网络传输等复杂因素的应用程序开发过程中,建议将该值设置为可配置的参数,通过调整该参数,使你的应用达到最好的性能。

参考资料:

1) Microsoft Knowledge Base 156932

2)  Microsoft Windows Internals, Fourth Edition.

你可能感兴趣的:(异步IO性能探究[转])