Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么MSVC 2010下的新建和删除在循环中如此缓慢_C++_New Operator_Delete Operator - Fatal编程技术网

C++ 为什么MSVC 2010下的新建和删除在循环中如此缓慢

C++ 为什么MSVC 2010下的新建和删除在循环中如此缓慢,c++,new-operator,delete-operator,C++,New Operator,Delete Operator,当我试图在循环中创建和删除该类的实例时,遇到了一个问题。 迭代的执行时间是完全不同的。据我所知,这与从内存中删除对象有关。但是,我不理解这种操作的行为。为什么时间不同?我怎么修理它?当我在一个单独的线程中删除对象时,时间是稳定的 class NODE{ public: NODE(){} NODE* add(NODE* node) { children.push_back(node); re

当我试图在循环中创建和删除该类的实例时,遇到了一个问题。 迭代的执行时间是完全不同的。据我所知,这与从内存中删除对象有关。但是,我不理解这种操作的行为。为什么时间不同?我怎么修理它?当我在一个单独的线程中删除对象时,时间是稳定的

class NODE{

    public:
        NODE(){}

        NODE* add(NODE* node)
        {
            children.push_back(node);
            return node;
        }

        virtual ~NODE()
        {
            for(vector<NODE*>::iterator it = children.begin(); it != children.end(); ++it)
            {
                delete *it;
            }
        }

        vector<NODE*> children;

};

NODE* create()
{
    NODE* node( new NODE() );

    for (int i=0; i<200;i++) {
        NODE* subnode = node->add( new NODE());
        for (int k=0; k<20; k++) subnode->add( new NODE());
    }

    return node;
}

int main()
{
    NODE* root;
    unsigned t;

    for (int i=0; i<30; i++){
        t = clock();
        cout << "Create... ";
        root = create();
        delete root;
        cout<< clock()-t << endl;
    }
}
类节点{
公众:
节点(){}
节点*添加(节点*节点)
{
子节点。推回(节点);
返回节点;
}
虚拟节点()
{
for(vector::iterator it=children.begin();it!=children.end();++it)
{
删除*它;
}
}
媒介儿童;
};
节点*create()
{
节点*节点(新节点());
对于(inti=0;iadd(newnode());
for(int k=0;kadd(new NODE());
}
返回节点;
}
int main()
{
节点*根;
无符号t;

对于(int i=0;i当您创建一个对象时,有时会为其分配一个新的内存块,有时会将其放入一个已经存在的块中。这将导致两次分配可能需要不同的时间

如果您想使时间分配和释放保持一致,请在应用程序内部处理它们-从该块中获取一大块内存和服务分配。当然,当您需要另一块时,导致这种情况发生的分配将花费更长的时间…但对于大块,这种情况应该很少发生


要使分配和解除分配占用的时间完全一致,唯一的方法是减慢快速分配的速度,直到它们占用任何请求所能花费的最大时间。这将是Harrison Bergeron的性能优化方法。我不推荐这种方法。

通常,无法预测内存分配/解除分配时间。例如,如果用户空间堆用完了页面,需要从内核请求更多的页面,以及稍后访问新分配的页面时触发页面错误,则时间可能会发生显著变化


因此,即使您继续使用大块内存实现自己的堆,您的分配时间也会有所不同,因为懒散是底层内存系统的本质。

如果您真的想知道为什么它很慢,您需要在它上运行一个真正的分析器,例如AMD,
时钟
并不是一个高预测计时器


每次运行不同的原因取决于底层系统的分页、CPU负载以及处理器是否缓存了数据。

存在实时堆,但通常是内存堆操作(动态分配和释放)这意味着运行时会发生变化,甚至没有很好的界限

问题是,当相邻的内存块出现时,您通常需要将它们合并到单个块中。如果不这样做,最终您只会有大量的小内存块,并且即使有足够的内存可供分配,大内存分配也可能会失败。在任何给定的调用中,可能需要合并,也可能不需要合并,以及所需的数量具体做法可能会有所不同。这完全取决于您的系统最近执行的分配/解除分配模式,这根本不是您可以计划的。因此我们称之为“非确定性”

如果你不喜欢这种行为,有两种可能:

  • 切换到使用实时堆。您的操作系统可能没有内置实时堆,因此您必须购买或下载一个实时堆,并将其用于所有内存操作。我过去使用过的一个是
  • 不要在主循环中执行动态内存分配/释放(IOW:初始化后不执行)。这就是我们实时程序员多年来训练自己编写代码的方式

  • 除了其他回答,你还必须考虑Visual C++ 10运行时堆是线程安全的。这意味着即使只有一个线程,你也会遇到一些开销促进堆操作是线程安全的。因此,你看到这样糟糕的结果的一个原因是使用通用但相当慢的堆实现。


    使用/不使用调试器会得到不同的计时,原因是特殊堆也相对较慢。

    动态分配较慢,mmkay?另外,您正在创建120000个节点项。您运行create 30次,每次创建生成200个子节点,即6000个对象,然后每个子节点再创建20个节点,即120000个项。F或参考,相关(几乎重复)来自同一用户的问题:通过
    mlock
    分配锁定在主RAM中的页面足以防止延迟分配。分配区块时会产生所有开销,而不是更晚。我理解这一点,但示例中的时间差可能是x*10。如果我不使用delete,新对象将是crea新内存块中的ted和时间不会增加。为什么会这样?循环只是一个例子。我没有实际的代码。但是为什么会有这么大的差异?@user713782-同样,这一切都取决于分配/释放的模式,以及系统的堆需要做多少工作才能按照它想要的方式将所有内容合并在一起。具体是什么ly导致大部分工作取决于所使用的算法。好的。但它解释了当在单独的线程中也使用解除分配时,时间不会增加?@user713782-为什么会这样?通常一个进程中的所有线程都使用相同的堆。当我在单独的线程中删除对象时,为什么时间是稳定的。