如何使用c++在Windows上提高读取数据的速度

How to increase speed of reading data on Windows using c++

本文关键字:读取 数据 速度 高读取 c++ 何使用 Windows      更新时间:2023-10-16

我正在使用CreateFile/ReadFile和缓冲大小为4096字节从卷快照读取数据块。我面临的问题是ReadFile太慢了,我能够在45秒内读取68439块即267 Mb,我如何提高速度?下面是我使用的一部分代码,

block_handle = CreateFile(block_file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(block_handle != INVALID_HANDLE_VALUE)
{
    DWORD pos = -1;
    for(ULONG i = 0; i < 68439; i++)
    {
        sectorno = (i*8);
        distance = sectorno * sectorsize;
        phyoff.QuadPart = distance;     
        if(pos != phyoff.u.LowPart)
        {
             pos=SetFilePointer(block_handle, phyoff.u.LowPart,&phyoff.u.HighPart,FILE_BEGIN);
             if (phyoff.u.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
             {
                 printf("SetFilePointer Error: %dn", GetLastError());
                 phyoff.QuadPart = -1;
                 return;
             }
        }
        ret = ReadFile(block_handle, data, 4096, &dwRead, 0);
        if(ret == FALSE)
        {
            printf("Error Read");
            return;
        }
        pos += 4096;
    }
}

我应该使用OVERLAPPED结构吗?或者可能的解是什么?注意:代码不是线程的

等待正面响应

我不太明白你为什么要用这些极其低级的系统功能。

就我个人而言,我使用C风格的文件操作(使用fopen和read)以及c++风格的操作(使用fstream和read,参见此链接)来读取原始二进制文件。从本地磁盘读取的速度大约为100MB/秒。

在你的情况下,如果你不想使用标准的C或c++文件操作,我的猜测是你的代码变慢的原因是由于你在每个块之后执行一个seek。你真的需要为每个块调用SetFilePointer吗?如果这些块是连续的,则不需要这样做。

另外,尝试不同的块大小,不要害怕超过1MB。

您的问题是碎片化的数据读取。您不能通过修改ReadFile参数来解决这个问题。你需要整理你的阅读。这里有三种方法:

  1. 整理磁盘上的数据

  2. 整理读的碎片。也就是说,收集所有需要的读取,但还不读取任何内容。将读取的数据按顺序排序。按顺序读取所有内容,尽可能跳过SetFilePointer(即顺序块)。这将大大加快总读取速度,但在第一次读取开始之前会引入延迟。

  3. 内存映射数据。将所有数据复制到内存中,并从内存中随机读取数据。这是否可能取决于总共有多少数据。

另外,您可能想要更花哨一些,并尝试使用缓存。当您读取一个数据块时,虽然下一次读取不是连续的,但它很可能很接近。因此,当读取一个块时,顺序地将附近的大量数据块读入内存。在下一次读取之前,检查新的读取是否已经在内存中-从而节省查找和磁盘访问。测试、调试和调优需要大量的工作,所以我不建议这样做,除非这是一个关键任务的优化。还要注意,您的操作系统和/或磁盘硬件可能已经在做这些事情了,所以准备好看不到任何改进。

  1. 如果可能的话,顺序读取(并告诉CreateFile您打算使用FILE_FLAG_SEQUENTIAL_SCAN顺序读取)。
  2. 避免不必要的查找。如果你是按顺序阅读,你不应该需要任何搜索。
  3. 读取较大的块(如典型簇大小的整数倍)。我相信Windows自己的文件拷贝使用的读取量是8mb而不是4kb。考虑使用系统分配粒度的整数倍(可从GetSystemInfo获得)。
  4. 从对齐的偏移量中读取(你似乎正在这样做)。
  5. 读取到与页面对齐的缓冲区。考虑使用VirtualAlloc来分配缓冲区。
  6. 请注意,文件碎片可能会导致昂贵的查找。你对此无能为力。
  7. 请注意,卷压缩可以使查找特别昂贵,因为它可能必须从头解压缩文件以找到文件中间的起始点。
  8. 请注意,卷加密可能会减慢速度。你能做的不多,但要注意。
  9. 请注意,其他软件,如反恶意软件,可能会扫描整个文件,每次你触摸它。更少的操作将最小化这种影响。