【问题标题】:How can I increase performance on this MFC code?如何提高此 MFC 代码的性能?
【发布时间】:2010-12-23 15:16:10
【问题描述】:

我进行文件搜索并且有目录的例外列表,问题是下面的代码递归地遍历硬盘驱动器上的所有文件。它有效,但速度很慢。因此,我需要帮助来优化其性能。提前致谢。

CFileFind finder;

    // build a string with wildcards
    CString strWildcard(directory);
    strWildcard += _T("\\*.*");

    // start working for files
    BOOL bWorking = finder.FindFile(strWildcard);

    while (bWorking)
    {
        bWorking = finder.FindNextFile();

        if (finder.IsDots())
            continue;

        // if it's a directory, recursively search it

        if (finder.IsDirectory())
        {
            CString str = finder.GetFilePath();
            if(NULL == m_searchExceptions.Find(str)){
                _recursiveSearch(str);
            }
            else{
                continue;
            }
        }
        //basic comparison, can be replaced by strategy pattern if complicated comparsion required (e.g. REGEX)
        if(0 == finder.GetFileName().CompareNoCase(m_searchPattern)){
            if(m_currentSearchResults.Find(finder.GetFilePath()) == NULL){
                m_currentSearchResults.AddHead(finder.GetFilePath());       
            }
        }
    }

【问题讨论】:

    标签: c++ mfc recursion performance file-search


    【解决方案1】:

    看起来你的m_currentSearchResults 是一个列表,每次你找到一个文件名时,如果它已经在列表中,你就会查找它。如果您有很多找到的文件(比如数百个),这可能会成为瓶颈,因为它具有O(N^2) 复杂性。如果是这种情况,请考虑使用CMap,因为它会为您提供O(log N) 搜索(集合甚至比地图更合适,但您在 MFC 中没有此功能,但您也可以使用标准库的std::set 代替)。

    【讨论】:

    • 另外,添加之前是否真的需要查看它是否已经存在于列表中?
    • @tenfour,实际上通常我们不会两次获得相同的 FilePath,在这种情况下,可以简单地追加到列表中。
    【解决方案2】:

    有多慢?你有介绍吗?如果您在硬盘上递归搜索文件,则极有可能是 I/O 受限,除了获得更快的存储硬件(如固态)之外,您无能为力。

    【讨论】:

    • 这是瓶颈,但我的问题主要是关于比当前实现更快地比较字符串。
    • @baris_a:如果是这种情况,那么您应该在问题中指出这一点,因为熟悉此处涉及的 API 调用的每个人都会看到枚举本身占用了 95% 以上的时间,而且你的比较只占不到 5%,根本不看比较。如果您担心,请询问比较本身。
    【解决方案3】:

    我认为您无法在此处优化性能。无论您在最终优化方面做什么,您都将在 FindFirstFileFindNextFile 此处(Windows API 调用)中花费 80+% 的时间。

    I asked a similar question already 尚未得到答复。

    【讨论】:

      【解决方案4】:

      您正在对文件进行一般搜索。有一百万种产品在这方面做得很好,它们都使用索引作为优化。这里的薄弱环节肯定是你的磁盘,而不是你的代码。与枚举磁盘上的 1,000,000 个文件所需的时间相比,比较 1,000,000 个字符串根本不需要时间。

      【讨论】:

        【解决方案5】:

        这里有两个关于性能的基本问题:硬盘访问和目录遍历。你们都可能能够优化。

        硬盘优化

        静止的硬盘往往会保持静止。一个旋转的圆柱体喜欢不停地旋转。因此,硬盘访问的瓶颈在于启动、寻道时间和读取时间。减少访问量并增加每次读取的数据量将提高您的性能。

        内存访问比硬盘访问更快。因此,将大块数据拖入内存,然后搜索内存。

        优化目录搜索。

        如果你愿意,想象一下“页面”树。树中的每个节点都是零个或多个目录或文件的目录。不幸的是,在大多数操作系统中,这种数据结构并未针对高效搜索进行优化。

        理想的情况是将所有相关目录拖入内存,然后搜索它们(在内存中)。一旦知道文件的位置,对文件的随机访问就会相对较快。问题是通过仅阅读相关目录来减少搜索时间;即减少不相关的目录读取次数。

        大多数在硬盘驱动器上执行文件搜索的应用程序都会读取驱动器并创建自己的优化数据结构。对于具有大量文件或文件搜索很少的大型硬盘驱动器,这可能不是最佳选择。

        如果可以,请告诉操作系统在内存中保留尽可能多的目录。

        提高性能:减少其他应用程序。

        对于某些应用程序,感知的性能时间取决于同时运行的其他应用程序。同时运行编译器和互联网搜索会减慢大多数其他应用程序的速度。因此,请尝试消除与您的同时运行的其他不必要的应用程序。此外,投资会提高您的应用程序的优先级。

        【讨论】:

          【解决方案6】:

          +1 配置文件首先确定。此外,这似乎是一个也可以使用Task Parallel Library 解决的问题 - 在您看到每个目录时启动一个任务,并使用您 CPU 上的所有这些内核 -

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-04-12
            • 2016-11-27
            • 2012-06-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多