C++ C++;映射性能-Linux(30秒)与Windows(30分钟)!

C++ C++;映射性能-Linux(30秒)与Windows(30分钟)!,c++,performance,stl,C++,Performance,Stl,我需要处理一个文件列表。不应对同一文件重复处理操作。我使用的代码是- using namespace std; vector<File*> gInputFileList; //Can contain duplicates, File has member sFilename map<string, File*> gProcessedFileList; //Using map to avoid linear search costs void processFile(F

我需要处理一个文件列表。不应对同一文件重复处理操作。我使用的代码是-

using namespace std;

vector<File*> gInputFileList; //Can contain duplicates, File has member sFilename
map<string, File*> gProcessedFileList; //Using map to avoid linear search costs

void processFile(File* pFile)
{
    File* pProcessedFile = gProcessedFileList[pFile->sFilename];
    if(pProcessedFile != NULL)
        return; //Already processed

    foo(pFile); //foo() is the action to do for each file
    gProcessedFileList[pFile->sFilename] = pFile;
}

void main()
{
    size_t n= gInputFileList.size(); //Using array syntax (iterator syntax also gives identical performance)
    for(size_t i=0; i<n; i++){
        processFile(gInputFileList[i]);
    }
}
使用名称空间std;
矢量文件列表//可以包含重复项,文件具有成员sFilename
映射gProcessedFileList//使用map避免线性搜索开销
作废处理文件(文件*pFile)
{
File*pProcessedFile=gpProcessedFileList[pFile->sFilename];
如果(pProcessedFile!=NULL)
return;//已处理
foo(pFile);//foo()是对每个文件执行的操作
gProcessedFileList[pFile->sFilename]=pFile;
}
void main()
{
size\u t n=gInputFileList.size();//使用数组语法(迭代器语法也提供相同的性能)

对于(size_t i=0;i我非常非常强烈地怀疑您的性能问题是否来自STL容器

尝试消除(注释掉)对
foo(pFile)
的调用或任何其他涉及文件系统的方法。虽然运行
foo(pFile)
一次可能看起来很快,但在1000个不同的文件上运行它(以我的经验,尤其是在Windows文件系统上)可能会慢得多(例如,由于文件系统缓存行为。)

编辑 您最初的帖子声称调试版本和发布版本都受到影响。现在您正在撤回该声明

请注意,在调试版本中:

  • STL实现执行以下操作: 额外检查和断言
  • 堆 操作(内存分配等) 执行额外的检查和断言; 此外,在debug下构建 是 禁用(总容量高达10倍 内存分配速度减慢)
  • 没有执行代码优化, 这可能会导致进一步的STL 性能下降(STL多次严重依赖内联、循环展开等)

  • 对于1000次迭代,您可能不会受到上述影响(至少不会在外部循环级别),除非您在foo()中大量使用STL/堆.

    在任意时间使用调试器闯入程序,堆栈跟踪很有可能会告诉您它在哪里花费时间。

    我会像处理任何性能问题一样处理它。这意味着:评测。顺便说一句,MSVC有一个内置的评测器,所以这可能是一个熟悉它的好机会它。

    如果您看到的性能问题与
    map
    类有任何关系,我会感到惊讶。执行1000次查找和1000次插入应该需要几微秒的时间。什么是
    foo()
    正在做什么?

    在不知道其余代码如何配合的情况下,我认为缓存处理过的文件的总体想法有点古怪


    首先尝试删除向量中的重复项,然后对它们进行处理。

    尝试对每个块或主要操作进行注释,以确定在Linux和Windows中哪个部分实际导致了执行时间的差异。我也不认为这是因为STL映射。问题可能出在foo()内部。这可能是在某些文件操作中,因为在这种情况下,这是我唯一能想到的代价高昂的事情


    您可以插入时钟()在操作之间调用以了解执行时间。

    您说,当您中断时,您发现自己在vector::add中。您向我们展示的代码中没有vector::add,因此我怀疑它在
    foo
    函数中。如果看不到该代码,就很难说出发生了什么


    在微软Visual Studio中,您可能无意中创建了一个算法。

    < P>,在访问标准的C++库时,存在一个全局锁,以防止调试生成中的多线程问题。这可能会导致大的性能命中。例如,我们的完整测试代码在50分钟内运行在Linux /GCC上,而Windows V上需要5小时。C++ 2008。注意,在发布模式编译时,不使用非调试VisualC++运行时,该性能不存在。

    如果您放弃映射并分区向量,则可以改进一些事情。这意味着重新排序输入文件列表。这也意味着您必须找到一种快速确定文件是否已PR的方法。可能通过在
    文件
    类中保留一个标志来处理。如果可以对文件列表重新排序,并且如果可以将脏标志存储在
    文件
    对象中,则可以将性能从O(n log m)提高到O(n),对于n个总文件和m个已处理文件

    #include <algorithm>
    #include <functional>
    // ...
    vector<File*>::iterator end(partition(inputfiles.begin(), inputfiles.end(),
                                          not1(mem_fun(&File::is_processed))));
    for_each(inputfiles.begin(), end, processFile);
    
    但是要小心:您处理的是指向同一地址的两个不同指针,两个容器中的每一对指针都是这样。确保只有一个指针拥有指针对象


    我不指望这两种方法都能解决性能问题,但无论如何。

    如果你大部分工作都是在linux上完成的,那么我强烈建议你只能在windows中编译到发行版模式。这会让生活更轻松,特别是考虑到所有windows不灵活的库处理问题。

    我怀疑ct问题不在于std::map,而在于File*类。您是否尝试过确定性能下降的阈值?Windows和linux对打开的文件数量有不同的限制。如果您注释掉
    foo()
    ,需要多长时间?要获取更多信息,请删除foo调用。这可能是Linux/Windows中STL、编译器或文件处理的不同。问题肯定不在于映射性能!上面的示例中没有std::vector add。已处理的文件已存储在映射中,因此该步骤是正确的。否,gProcessedFileList[]是已处理文件的缓存,以避免重复重新处理同一文件。我将检查文件是否正在关闭。1.在第一篇文章发表时,我无意中检查了调试版本的行为,认为这是发布版本。对此我很抱歉。2.foo()也大量使用STL…正如我之前所做的那样
    vector<File*> processed(inputfiles.size(), 0);
    
    for( vector<File*>::size_type i(0); i != inputfiles.size(); ++i ) {
        if( processed[i] != 0 ) return;  // O(1)
        // ...
        processed[i] = inputfiles[i];    // O(1)
    }