ディレクトリ内に存在するファイル数の取得方法の比較

あるディレクトリ内のファイル(+ディレクトリ)数を取得する必要があったのですが,Boost.Filesystem と FindFirstFile とでどの程度の速度差になるのかなと思い調べてみました.まず,Boost.Filesystem 版のファイル数カウント関数.

#include <string>
#include <boost/filesystem.hpp>

std::size_t file_count_boost(const boost::filesystem::path& root) {
    namespace fs = boost::filesystem;
    if (!fs::exists(root) || !fs::is_directory(root)) return 0;
    
    std::size_t result = 0;
    fs::directory_iterator last;
    for (fs::directory_iterator pos(root); pos != last; ++pos) {
        ++result;
        if (fs::is_directory(*pos)) result += file_count_boost(pos->path());
    }
    
    return result;
}

次に FindFirstFile を使ったファイル数カウント関数.

#include <string>
#include <windows.h>
#include <tchar.h>

std::size_t file_count_native(const std::basic_string<TCHAR>& src) {
    std::basic_string<TCHAR> root = src + _T("\\*.*");
    WIN32_FIND_DATA wfd = {};
    HANDLE handle = FindFirstFile(root.c_str(), &wfd);
    if (handle == INVALID_HANDLE_VALUE) return 0;
    
    std::size_t result = 0;
    do {
        std::basic_string<TCHAR> path(wfd.cFileName);
        if (path != _T(".") && path != _T("..")) {
            ++result;
            if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) result += file_count_native(src + _T('\\') + path);
        }
    } while (FindNextFile(handle, &wfd));
    FindClose(handle);
    
    return result;
}

実行結果

テストは,実行環境にある boost_1_46_1 ディレクトリを指定して調べてみました.実行環境の boost_1_46_1 ディレクトリには,37,834 ファイルと 3,233 ディレクトリが存在するようです.

Boost.Filesystem を使用した場合
$ time ./file-scanning-test.exe
41067

real    0m3.135s
user    0m0.000s
sys     0m0.015s

FindFirstFile を使用した場合
$ time ./file-scanning-test.exe
41067

real    0m0.363s
user    0m0.031s
sys     0m0.000s

実行すると 1桁くらい実行速度が変わっていました.さすがに 1桁も変わるとは思っていなかったので驚きました.やはり変なものを指定される(馬鹿でかいファイルとか)可能性のある部分は,ネイティブ(ここだと Win32 API)で書いておかないとまずい場合があると言う事でしょうか.