我正在读取一个文件,并且要么读取一行数据(1600个连续读取的17个字节),要么读取一列数据(以1600 * 17 = 27,200个字节分隔的17个字节的1600个读取)。 该文件位于本地驱动器或远程驱动器上。 我读取10次,所以我希望在每种情况下读取272,000字节的数据。
在本地驱动器,我看到了我的期望。 在远程驱动器上按顺序阅读时,我也看到了我所期望的,但是当阅读一个专栏时,我看到大量额外的读取正在完成。 它们的长度为32,768字节,似乎没有被使用,但是它们使得读取的数据量从272,000字节跳到79MB到106MB的任何地方。 这是使用进程监视器的输出:
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操作:读取,偏移量:9,390,069,长度: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-caching,寻呼I / O,同步寻呼I / O,优先级:正常 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操作:读取,偏移:9,417,269,长度: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目录\ BPepers_Temp \ Projects \ PT_4 \ Horizons \ BaseName3D_1 \ RR_AP SUCCESS操作:读取,偏移量:9,444,469,长度: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-caching,寻呼I / O,同步寻呼I / O,优先级:正常 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操作:读取,偏移量:9,471,669,长度: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操作:读取,偏移量:9,498,869,长度: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-caching,寻呼I / O,同步寻呼I / O,优先级:正常
请注意,I / O标志设置为非高速caching,分页I / O,同步分页I / O,优先级:正常,额外读取32,768。 这些额外的读取是从272 KB到106 MB,并造成缓慢。 从本地文件读取时,或者如果我正在读取一行,所以它们都是连续的。
我试着设置FILE_FLAG_RANDOM_ACCESS,但似乎没有帮助。 任何想法是什么导致这些额外的读取,以及如何使他们停止?
testing正在Vista 64位系统上运行。 我可以提供一个程序的源代码来演示这个问题,以及一个执行testing的控制台程序。
你可能会遇到smb的操作锁问题。 通常,当通过网络读取/保存文件时,窗口将把整个文件拖到客户机上并发送更改。 当您使用平面文件数据库或文件时,可能会导致smb文件共享中不必要的读取。
我不知道是否有一种方法只是将整个文件拉过来,从本地副本上的文件中读取行,然后再推回所做的更改。
你会看到一些关于oplocks和平面文件数据库的恶梦。
http://msdn.microsoft.com/en-us/library/aa365433%28VS.85%29.aspx
不知道这是否能解决您的问题,但可能会让您指出正确的方向。 祝你好运!
我找到了答案。 Windows通过页面缓存进行文件读取,所以当我读取17个字节时,它首先必须传输一个32K的整页,然后才能将我想要的17个字节复制到页面缓存中。 性能恶劣的结果!
同样的事情实际上是在本地文件第一次读取完成的情况下发生的,因为在这种情况下,它仍然一次将全部页面加载到页面缓存中。 但是,我第二次在本地运行测试,这些文件都已经在页面缓存中,所以我没有看到它。 如果SuperFetch打开,我已经做了这些测试了一段时间,Windows将开始加载文件到缓存之前,我甚至运行我的测试应用程序,所以我再也看不到页面读取完成。
所以操作系统在幕后做了很多事情,这使得很难做好性能测试!
我一直都在看这个,而且这是无法控制的:网络做到了自己想要的。
如果你知道这个文件将小于1MB,那就把整个东西放到内存中。
我的猜测是,操作系统正在自己对文件进行预读,以免在稍后需要数据。 如果它不伤害你,那么它应该不重要。
检查CreateFile API的缓存行为部分。
您可能想尝试“FILE_FLAG_NO_BUFFERING”来查看是否停止了额外的读取。 被警告,使用这个标志可能会减慢你的应用程序。 通常情况下,如果您了解如何尽可能快地将数据从磁盘上流式传输,并且操作系统缓存功能正在实现,那么您可以使用此标志。
此外,如果使用“FILE_FLAG_SEQUENTIAL_SCAN”标志,则可能可以获得与本地文件的网络文件相同的行为。 这个标志暗示了Windows缓存管理器你将要做的事情,并且会尝试提前为你提供数据。
我认为SMB总是传输一个块,而不是一小部分字节。
有关块大小协商的一些信息可以在这里找到。 http://support.microsoft.com/kb/q223140
所以你看到一个读取复制相关的块,然后在块内部读取17个字节的本地数据。 (如果查看模式,则有一对17字节读取,其中两个读取落在同一个块中)。
修复显然取决于您对应用程序的控制以及数据库的大小和结构。 (例如,如果数据库每个文件只有一列,那么所有的读取都是顺序的,如果使用数据库服务器,则不会使用SMB等)
如果有任何安慰, iTunes也会在使用网络驱动器的时候表现得非常糟糕 。