C++ 加快NTFS文件枚举(使用FSCTL_ENUM_USN_数据和NTFS MFT/USN日志)

C++ 加快NTFS文件枚举(使用FSCTL_ENUM_USN_数据和NTFS MFT/USN日志),c++,performance,winapi,ntfs,ntfs-mft,C++,Performance,Winapi,Ntfs,Ntfs Mft,我通过查看NTFS MFT/USN日志来枚举NTFS硬盘分区的文件,其中包含: HANDLE hDrive = CreateFile(szVolumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); DWORD cb = 0; MFT_ENUM_DATA med = { 0 }; med.StartFileReferenceNumber = 0; med.LowUs

我通过查看NTFS MFT/USN日志来枚举NTFS硬盘分区的文件,其中包含:

HANDLE hDrive = CreateFile(szVolumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
DWORD cb = 0;

MFT_ENUM_DATA med = { 0 };
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = MAXLONGLONG;      // no change in perf if I use med.HighUsn = ujd.NextUsn; where "USN_JOURNAL_DATA ujd" is loaded before

unsigned char pData[sizeof(DWORDLONG) + 0x10000] = { 0 }; // 64 kB

while (DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL))
{
        med.StartFileReferenceNumber = *((DWORDLONG*) pData);    // pData contains FRN for next FSCTL_ENUM_USN_DATA

       // here normaly we should do: PUSN_RECORD pRecord = (PUSN_RECORD) (pData + sizeof(DWORDLONG)); 
       // and a second loop to extract the actual filenames
       // but I removed this because the real performance bottleneck
       // is DeviceIoControl(m_hDrive, FSCTL_ENUM_USN_DATA, ...)
}
它可以工作,比通常的
FindFirstFile
枚举技术快得多。但我发现它还不是最优的:

  • 在我的700k文件
    C:\
    上,需要21秒。(必须在重新启动后执行此措施,否则,由于缓存的原因,此措施将不正确)

  • 我见过另一个索引软件(不是所有的,另一个)能够在<5秒内(Windows启动后测量)索引
    C:\
    ,而无需读取.db文件中预先计算的数据库(或其他类似的技巧,可以加快速度!)。此软件不使用
    FSCTL_ENUM_USN_DATA
    ,而是使用低级NTFS解析

我努力提高绩效的内容

  • 使用另一个标志打开文件,如
    文件标志\u顺序\u扫描
    文件标志\u随机访问
    ,或
    文件标志\u无缓冲
    :相同结果:21秒读取

  • 看,, 我对它们进行了深入研究,但它并没有回答这个实际问题

  • 测试另一个编译器:MinGW64而不是VC++Express 2013:相同的性能结果,没有差异

  • 在VC++上,我已经切换到
    Release
    而不是
    Debug
    :是否有其他项目属性/选项可以加速程序

问题

是否有可能提高性能
设备控制(hDrive、FSCTL\u ENUM\u USN\u DATA等)

还是提高性能的唯一方法是对NTFS进行低级手动解析



注意:根据测试,在这些
设备控制(hDrive、FSCTL\u ENUM\u USN\u DATA,…)
期间,我的700k文件要读取的总大小仅为84MB。21秒读取84MB的速度只有4MB/秒(我有一个SSD!)。可能还有一些性能改进的空间,你不这样认为吗?

最明显的尝试是增加缓冲区大小以减少往返次数。但我认为这不会大大提高性能,瓶颈很可能是将记录从任何底层格式转换为USN_RECORD_Vx结构。谢谢@HarryJohnston。我尝试过4kb缓冲区大小,64kb,1MB(带有
#pragma注释(linker,“/STACK:2000000”)
),甚至是一个100MB
malloc
-ed数组,都是一样的:~21秒。你可能是对的@HarryJohnston,瓶颈似乎是转换到USN\u RECORD\u Vx结构。你认为有没有办法强制选择“更轻的转换”(我不关心很多信息,我只需要:FileReferenceNumber、ParentFolder、filename)?我不认为这是可能的:“这个软件不使用<代码> FSCTLYMULTION UnnDATA < /COD>,而是低级NTFS解析。”——“这不是你的问题的答案吗?”IcTestTi我希望在1到中间有一些解决办法。代码>FSCTL_ENUM_USN_数据,具有“正常性能”,易于编码和2。超级超级快速低级NTFS解析,需要一周的全职时间才能正常工作。。。你认为这个中间点存在吗?