【问题标题】:Is it possible to dynamically change from FILE_FLAG_SEQUENTIAL_SCAN to FILE_FLAG_RANDOM_ACCESS?是否可以从 FILE_FLAG_SEQUENTIAL_SCAN 动态更改为 FILE_FLAG_RANDOM_ACCESS?
【发布时间】:2011-05-16 16:48:44
【问题描述】:

下午好,我们正在使用 Windows 和 Linux 的内存映射文件 API 构建 Windows/LINUX 重复数据删除器的原型。我们的重复数据删除器首先对所有要重复数据删除的数据库记录进行顺序扫描。因此,在对要删除的数据库记录进行初始顺序扫描期间,我们将标志 FILE_FLAG_SEQUENTIAL_SCAN 传递给 Windows API CreateFile。 完成重复数据删除过程的第一部分后,我们尝试使用 Windows 内存映射 API 随机访问数据。此时,使用Windows C++ API,是否可以动态更改为FILE_FLAG_RANDOM_ACCESS模式?

In Linux, we are are able to do this with the following excerpt of code, 
  MapPtr = (char*)mmap((void *)BaseMapPtr ,mappedlength,PROT_READ, 
            MAP_PRIVATE,  hFile,baseoff );
                    if (MapPtr == MAP_FAILED){
                        perror("mmap");
                        throw cException(ERR_MEMORYMAPPING,TempFileName);
                    }
 madvise(MapPtr,mappedlength,MADV_RANDOM);

我们是否在重复数据删除过程的随机访问阶段使用 FILE_FLAG_SEQUENTIAL_SCAN 在 Windows 中付出了代价。谢谢。

【问题讨论】:

    标签: c++ windows linux


    【解决方案1】:

    传递给 CreateFile() 的缓存提示标志不会影响内存管理器满足通过取消引用映射部分中的地址而产生的页面错误的方式。此类 I/O 使用相同的 - 它们使用与常规 I/O 相同的缓存页面。

    也就是说,当使用 FILE_FLAG_SEQUENTIAL_SCAN 创建文件句柄时,缓存管理器可以执行预读操作(如果系统条件允许,甚至可以将整个文件读入内存)。这意味着如果您按顺序访问映射文件的页面,您可能会遇到更少的硬页面错误。

    在我看来,最好的方法是简单地重新使用您在重复数据删除处理过程中创建的句柄。关闭和重新打开可能会导致文件之前缓存的页面被丢弃,具体取决于缓存压力。

    【讨论】:

    • 感谢您的回答。我刚刚接受了你的回答。我将更改我们的代码以重用我们在重复数据删除处理期间创建的句柄。我们注意到,当使用 FILE_FLAG_SEQUENTIAL_SCAN 创建文件句柄时,我们在顺序访问映射文件的页面时遇到的硬页面错误较少。这是否意味着我们在重复数据删除处理期间不尝试使用 FILE_FLAG_RANDOM_ACCESS?谢谢。
    • @Frank - 您的里程可能会有所不同。当指定 FILE_FLAG_RANDOM_ACCESS 时,将禁用句柄的预读。此外,缓存管理器在取消映射之前访问过的文件页面时不会那么激进——这里的想法是在应用程序重新访问页面时最小化文件的映射/取消映射事件。
    • 感谢您的回答。我认为我们将尝试使用 CreateFile(...,FILE_FLAG_RANDOM_ACCESS) 运行我们的重复数据删除应用程序,以便在重复数据删除应用程序重新访问页面时最小化内存映射文件的映射/取消映射事件。看到结果应该很有趣。谢谢。
    【解决方案2】:

    可以在此处找到有关 FILE_FLAG_SEQUENTIAL_SCAN 工作原理的说明:http://support.microsoft.com/kb/98756

    由于它仅与 CreateFile 函数一起使用,因此一旦打开文件就无法更新它。您可以随时关闭文件并使用不同的标志重新打开它。

    【讨论】:

    • 感谢您的回答,我刚刚接受了您的回答。您是否建议在我们的重复数据删除程序的第一个顺序扫描阶段之后,我们关闭文件。那么,在最后的随机访问阶段,我们是否应该使用 FILE_FLAG_RANDOM_ACCESS 重新打开文件?这会影响我们使用 Window Memory Mapping File API 的能力吗?谢谢。
    • 我们现在正在尝试您的建议。所以我们: 1. close(hFile) 2. hFile = CreateFile((LPTSTR) TempFileName,.... Flags_ | FILE_FLAG_RANDOM_ACCESS); 3.Distance_.LowPart = (ULONG)FileSize_;距离_.HighPart = 0; 4. dwPtr = ::SetFilePointer(hFile,Distance_.LowPart, &(Distance_.HighPart), FileBegin); 5. SetEndOfFile(hFile); 6. hMapping=::CreateFileMapping(hFile,(SECURITY_ATTRIBUTES *)Security_,PAGE_READWRITE,0,0,0);谢谢。
    • @Frank:你传递的标志不影响文件I/O的正常操作,它只是因为缓冲而影响效率。内存映射完全有可能完全绕过缓冲,我不确定。
    • 感谢您的回复。我想我们确定内存映射是否完全绕过缓冲的唯一方法是在你的建议之后分析代码?我们将尽力让您知道我们今晚的测试结果。谢谢。
    • 我很抱歉没有让你知道我们昨晚的结果。我不得不重建我的 sqlite 数据库。我想知道您是否阅读了@Buke 的答案(上图)。你和@Bukes 说的是基本相同的想法吗?感谢您的帮助。
    【解决方案3】:

    只是为了备份@Burkes 的回答:正如你提到的,你“使用 Windows 的内存映射文件 API”,应该注意 Raymond Chen warns the cache hints have no affect on effect on memory mapped I/O

    注意:这些缓存提示仅在您使用 ReadFile(或道德等价物)时适用。内存映射文件访问不通过缓存管理器,因此这些缓存提示无效。

    因此,已经缓存的内容可能会有所帮助,但未来的内存映射访问将无助于缓存的填充/取消填充。

    【讨论】:

      猜你喜欢
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多