我正在读取一个文件,我要么读取一行数据(1600个连续读取17个字节)或一列数据(1600个读取17个字节,由1600 * 17 = 27,200个字节分隔)。该文件位于本地驱动器或远程驱动器上。我读取了10次,所以我希望在每种情况下读取272,000个字节的数据。
在本地驱动器上,我看到了我的期望。在按顺序阅读的远程驱动器上,我也看到了我的期望,但在读取列时,我看到正在进行大量的额外读取。它们长度为32,768字节,似乎没有使用,但它们使读取的数据量从272,000字节跳到79 MB到106 MB。以下是使用Process Monitor的输出:
1:39:39.4624488 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,390,069, Length: 17 1:39:39.4624639 PM DiskSpeedTest.exe 89628 FASTIO_CHECK_IF_POSSIBLE \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Operation: Read, Offset: 9,390,069, Length: 17 1:39:39.4624838 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,388,032, Length: 32,768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal 1:39:39.4633839 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,417,269, Length: 17 1:39:39.4634002 PM DiskSpeedTest.exe 89628 FASTIO_CHECK_IF_POSSIBLE \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Operation: Read, Offset: 9,417,269, Length: 17 1:39:39.4634178 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,444,469, Length: 17 1:39:39.4634324 PM DiskSpeedTest.exe 89628 FASTIO_CHECK_IF_POSSIBLE \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Operation: Read, Offset: 9,444,469, Length: 17 1:39:39.4634529 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,441,280, Length: 32,768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal 1:39:39.4642199 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,471,669, Length: 17 1:39:39.4642396 PM DiskSpeedTest.exe 89628 FASTIO_CHECK_IF_POSSIBLE \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Operation: Read, Offset: 9,471,669, Length: 17 1:39:39.4642582 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,498,869, Length: 17 1:39:39.4642764 PM DiskSpeedTest.exe 89628 FASTIO_CHECK_IF_POSSIBLE \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Operation: Read, Offset: 9,498,869, Length: 17 1:39:39.4642922 PM DiskSpeedTest.exe 89628 ReadFile \\BCCDC01\BCC-raid3\SeisWareInc Temp Dir\BPepers_Temp\Projects\PT_4\Horizons\BaseName3D_1\RR_AP SUCCESS Offset: 9,498,624, Length: 32,768, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
请注意32,768的额外读取,I / O标志设置为非缓存,寻呼I / O,同步寻呼I / O,优先级:正常。这些额外的读取是从272 KB到106 MB,并导致缓慢。当从本地文件中读取或者我正在读取一行时,它们不会发生,因此它们都是顺序的。
我尝试过设置FILE_FLAG_RANDOM_ACCESS,但似乎没有帮助。关于什么导致这些额外读取以及如何使它们停止的任何想法???
测试正在Vista 64位系统上运行。我可以提供程序的源代码来演示问题以及执行测试的控制台程序。
答案 0 :(得分:2)
您可能会遇到smb上的操作锁定问题。通常,当通过网络读取/保存文件时,窗口会将完整文件拉到客户端上,然后发回更改。使用平面文件数据库或文件时,它可能会导致在smb文件共享中进行不必要的读取。
我不确定是否有办法只是拉过整个文件,从本地副本上读取该文件中的行,然后再推回更改。
你会读到一些关于oplocks和平面文件数据库的噩梦。
http://msdn.microsoft.com/en-us/library/aa365433%28VS.85%29.aspx
不确定这是否能解决您的问题,但它可能会让您指向正确的方向。祝你好运!
答案 1 :(得分:2)
我找到了答案。 Windows通过页面缓存进行文件读取,因此当我读取17个字节时,它首先必须传输32K的整页,然后才能将我想要的17个字节复制到页面缓存中。表现令人讨厌!
同样的事情实际上是在第一次对本地文件进行读取时发生的事情,因为在这种情况下它仍然会一次将整页加载到页面缓存中。但是我第二次在本地运行测试时,文件都已经在页面缓存中,所以我没有看到它。如果打开SuperFetch并且我已经进行了一段时间的测试,Windows将开始将文件加载到缓存之前我甚至运行我的测试应用程序,所以我再也看不到页面读完了。
因此操作系统在幕后做了很多事情,这使得很难完成良好的性能测试!
答案 2 :(得分:0)
我一直都看到这一点,而且它超出了你的控制范围:网络做了它想做的事情。
如果您知道该文件将小于1MB,只需将整个内容拉入内存即可。
答案 3 :(得分:0)
我的猜测是操作系统正在自行预读文件,因为您需要稍后获取数据。如果没有伤害你那么它应该没关系。
查看CreateFile API的caching behavoir部分。
您可能想尝试'FILE_FLAG_NO_BUFFERING'以查看是否停止额外读取。请注意,使用此标志可能会降低您的应用程序速度。通常,如果您了解如何尽可能快地从磁盘上流式传输数据并且操作系统缓存只会妨碍您使用此标志。
如果您使用'FILE_FLAG_SEQUENTIAL_SCAN'标志,您也可以获得与具有本地文件的网络文件相同的行为。这个标志提示你将在Windows缓存管理器中做什么,并会尝试提前为你获取数据。
答案 4 :(得分:0)
我认为SMB总是传输一个块,而不是一小块字节。
可以在此处找到有关块大小协商的一些信息。 http://support.microsoft.com/kb/q223140
所以你看到一个读取来复制相关的块,然后是块内17个字节的本地读取。 (如果查看模式,有一些17字节读取对,其中两个读取属于同一个块)。
修复显然取决于您对应用程序的控制以及数据库的大小和结构。 (例如,如果数据库每个文件有一列,则所有读取都是顺序的。如果使用数据库服务器,则不会使用SMB等。)
如果有任何安慰,iTunes performs abysmally when using a network drive too。