1
编译器:Microsoft C++ 2005
硬件:AMD 64 位 (16 GB)


提交对 18GB 文件的顺序只读访问,具有以下时序、文件访问和文件结构特征:

18,184,359,164(文件长度)
11,240,476,672(ntfs 压缩文件长度)

时间文件方法盘
14:33?压缩的 fstream 固定磁盘
14:06 正常fstream固定盘
12:22 正常winapi固定盘
11:47 压缩winapi固定盘
11:29 压缩的 fstream ram 磁盘
10:37 压缩的 winapi ram 磁盘
 7:18 压缩 7z 存储解压到 ntfs 12gb ram 磁盘
 6:37 正常复制到同卷硬盘



fstream 构造函数和访问:

定义缓冲区大小 524288
    无符号整数兆字节 = 缓冲区大小;
    字符 * 数据缓冲区0;databuffer0 = (char*) malloc (mbytes);
    datafile.open("drv:/file.ext", ios::in | ios::binary );
    datafile.read (databuffer0, mbytes);


winapi构造函数和访问:

定义缓冲区大小 524288
    无符号整数兆字节 = 缓冲区大小;
    const TCHAR* const filex = _T("drv:/file.ext");
    字符 ReadBuffer[BUFFERSIZE] = {0};
    hFile = CreateFile(filex, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    如果(假 == ReadFile(hFile,ReadBuffer,BUFFERSIZE-1,&dwBytesRead,NULL))
    { ...

对于 fstream 方法,-> 16MB 缓冲区大小不会减少处理时间。对于 winapi 方法,超过 .5MB 的所有缓冲区大小均失败。哪些方法可以优化此实现与处理时间?

4

2 回答 2

0

尝试这个。

hf = CreateFile(..... FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED ...)

然后是阅读循环。在 iPad 上打字时省略了一些小细节......

int bufsize =4*1024*1024;
CEvent e1;
CEvent e2;
CEvent e3;
CEvent e4;
unsigned char* pbuffer1 = malloc(bufsize);
unsigned char* pbuffer2 = malloc(bufsize);
unsigned char* pbuffer3 = malloc(bufsize);
unsigned char* pbuffer4 = malloc(bufsize);
int CurOffset = 0;

do {
   OVERLAPPED r1;
   memset(&r1, 0, sizeof(OVERLAPPED));
   r1.Offset = CurOffset;
   CurOffset += bufsize;
   r1.hEvent = e1;
   if (! ReadFile(hf, pbuffer1, bufsize, bufsize, &r1)) {
       // check for error AND error_handle_eof (important)
   }

   OVERLAPPED r2;
   memset(&r2, 0, sizeof(OVERLAPPED));
   r2.Offset = CurOffset;
   CurOffset += bufsize;
   r2.hEvent = e2;
   if (! ReadFile(hf, pbuffer2, bufsize, bufsize, &r2)) {
       // check for error AND error_handle_eof (important)
   }

   OVERLAPPED r3;
   memset(&r3, 0, sizeof(OVERLAPPED));
   r3.Offset = CurOffset;
   CurOffset += bufsize;
   r3.hEvent = e3;
   if (! ReadFile(hf, pbuffer3, bufsize, bufsize, &r3)) {
       // check for error AND error_handle_eof (important)
   }

   OVERLAPPED r4;
   memset(&r4, 0, sizeof(OVERLAPPED));
   r4.Offset = CurOffset;
   CurOffset += bufsize;
   r4.hEvent = e4;
   if (! ReadFile(hf, pbuffer1, bufsize, bufsize, &r4)) {
       // check for error AND error_handle_eof (important)
   }

   // wait for events to indicate data present
   // send data to consuming threads
   // allocate new buffer
} while ( not eof, etc )

以上是您需要的骨骼。我们使用它来实现高 I/O 吞吐率,但您可能需要稍微改进它以实现最终性能。我们发现 4 个出色的 I/O 最适合我们使用,但这会因平台而异。每个 IO 读取不到 1Mb 对性能不利。读取缓冲区后,不要在读取循环中使用并使用它,发布到另一个线程并分配另一个缓冲区(但从重用队列中获取它们,不要继续使用 malloc)。上面的总体意图是尝试保持 4 个未完成的 IO 对磁盘开放,一旦你没有这个,整体性能就会下降。

此外,这在只读取文件的磁盘上效果最好。如果您同时开始在同一个磁盘上读取/写入不同的文件,性能会迅速下降,除非您有 SSD 磁盘!

不知道为什么您的 readfile 因 0.5Mb 缓冲区而失败,只需仔细检查一下,我们的实时产品代码正在使用 4Mb 缓冲区

于 2013-04-20T21:45:24.917 回答
0

您是否尝试过对文件进行内存映射?在我的测试中,这始终是读取大文件的最快方法。

更新:这是内存映射文件的旧但仍然准确的描述:http: //msdn.microsoft.com/en-us/library/ms810613.aspx

于 2013-04-19T08:08:16.147 回答