IEnumIDList::NextとFindFirstFileの速度

興味があったので計測してみた。
どこまで信頼できるか分からないけど、3回計測したものの平均。


ファイル数 IDL FFF IDL(i) FFD(i) IDL(FD)
C:\
10 0ms 0ms 0ms 16ms 0ms
(d)10 0 0 0 15 0
100 0 0 0 16 0
3000 15 16 47 469 16
LAN
10 0 0 0 31 0
(d)10 16 0 31 78 16
100 313 406 329 609 375
3000 13860 14286 14078 21375 14075
VPN
10 78 109 78 2485 78
(d)10 937 125 2328 4937 969
100 469 547 437 22438 458
3000 14141 14281 14343 652812 14250

*IDL IEnumIDList::Nextで列挙
*FFF FindFirstFile、FindNextFileで列挙
*(i) アイコン取得を追加
*(FD) WIN32_FIND_DATA取得を追加
*LAN 単なるHUB越え
VPN 光とCATV(下30M, 上2M)
*(d) desktop.iniでアイコンを設定したフォルダが1つ存在する

これ以外にもFindFirstFile系とIEnumIDList::Nextを比較したけど、
アイコンの取得を行わない場合に限って言えば、
ファイル数が少ない場合はFindFirstFileの方が速く、
ファイル数が多い場合はIEnumIDList::Nextが速い。


desktop.iniがある場合(アイコンを設定していなくても)、
IEnumIDList::Nextは遅くなるが、FindFirstFile系は遅くならない。


アイコンを取得する場合はIEnumIDList::Nextの圧勝。
VPNでSHGetFileInfoをSHGFI_PIDLなしで使うと遅すぎる。


IEnumIDList::NextでWIN32_FIND_DATAを取得してもほとんど遅くならない。


// IEnumIDList::Next
hr = sf->EnumObjects(hwnd,
SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN, &el);
if (hr != S_OK) return;

// WIN32_FIND_DATA取得の場合
//IShellFolder2* sf2;
//hr = sf->QueryInterface(IID_IShellFolder2, (LPVOID*)&sf2);

LPITEMIDLIST il;
ULONG fetched;
while (el->Next(1, &il, &fetched) == S_OK) {
// アイコン取得の場合
// int icon = ::SHMapPIDLToSystemImageListIndex(sf, il, NULL);

// WIN32_FIND_DATA取得の場合
// SAFEARRAY* sa = var.parray;
// WIN32_FIND_DATA* HUGEP fd;
// ::SafeArrayAccessData(sa, (void**)&fd);
// ::SafeArrayUnaccessData(sa);
// ::VariantClear(&var);
::CoTaskMemFree(il);
}

// FindNextFile
WIN32_FIND_DATA fd;
SHFILEINFO sfi;
HANDLE find = ::FindFirstFile(path.c_str(), &fd);
for (BOOL b=(find!=INVALID_HANDLE_VALUE); b; b=::FindNextFile(find, &fd)) {
// アイコン取得の場合
//wstring name = parent + fd.cFileName;
//::SHGetFileInfo(name.c_str(), NULL, &sfi, sizeof(SHFILEINFO),
// SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
//int icon = sfi.iIcon;
}

FindClose(find);