向量移动构造函数比复制构造函数要慢
我正在处理我的第一个C++项目,它是一个CSV解析器(full source code here)。它正在工作,现在我想要进行基本的重构/提高性能。向量移动构造函数比复制构造函数要慢
目前解析器的工作方式是通过返回每一行作为std::vector<std::string>
,我认为,而不是分配一个新的向量和一个新的字符串,每次我只有一个内部向量和内部字符串保留内存我会一再清除。
这工作,我开始寻找其他地方,我可能会做内存分配,我看到这个函数拷贝内部矢量,然后将其清除:
auto add_row() -> std::vector<std::string> { auto row(m_bufvec);
m_bufvec.clear();
return row;
}
我想,如果我而不是改变了这一行
auto row(m_bufvec);
到
auto row(std::move(m_bufvec));
它会导致以s因为根据http://en.cppreference.com/w/cpp/container/vector/vector,它需要一定的时间而不是线性的。令我惊讶的是,它使解析器明显变慢(根据我的真实粗糙基准运行time ./main.o
而不是this file)。
我完全不熟悉优化,基准测试和调整C++代码所带来的一切。也许这种优化是无用的,即使它的工作,但不管,我很好奇为什么std::move
导致放缓。我错过了什么吗?
回答:
复制bufvec时,其容量不变,但移动时容量将被清除。因此,稍后当您填写bufvec时,会进行对数分配以再次扩大其容量,这种分配可能很容易成为您的性能瓶颈。
移动版本使功能更快。但它使其他代码变慢。微型优化不能可靠地使程序更快。
编辑由OP:
通过在m_bufvec.reserve(row.size())
移动后的评论Cheers and hth. - Alf
提出的解决方案解决了这个问题,并确认上述推理是正确的。此外,它更有效率,(尽管只是略微),因为
你避免复制项目[在bufvec]。如果这些项目是简单的整数值,那并不重要。如果物品是例如字符串,动态分配,那么它确实很重要。
回答:
事实上,第一个版本预计会更快。其原因是:
auto row(m_bufvec);
调用拷贝constuctor,刚刚在一次分配必要的内存row
。 bufvec
也保留其分配的内存。因此,每个元素的分配被最小化,并且这很重要,因为它们涉及一定数量的重定位。
在第二个版本, 编辑 上面解释了主要问题中的“意外”结果。最后,事实证明,“理想”这个操作间移动,然后马上预约:auto row(std::move(m_bufvec));
bufvec
的记忆变成由row
拥有的,这种操作比拷贝构造函数更快。但是由于bufvec
已经失去了分配的内存,当你以后逐元素地填充它时,它会做很多重新分配和(昂贵的)重定位。重新分配的数量通常与矢量的最终大小成对数。auto row(std::move(m_bufvec);
m_bufvec.reserve(row.size());
return row;
这实现了三个目标:
没有元素乘元素分配
没有无用的初始化
bufvec
没有无用的从
m_bufvec
元素复制到row
。
以上是 向量移动构造函数比复制构造函数要慢 的全部内容, 来源链接: utcz.com/qa/262430.html