【问题标题】:Cost of copy vs move std::shared_ptr复制成本与移动 std::shared_ptr
【发布时间】:2021-12-31 08:34:20
【问题描述】:

Why would I std::move an std::shared_ptr?

对这个问题的回答指出,移动std::shared_ptr 与速度有关,但没有人详细解释为什么它更快。相比之下,它到底有多贵?当一个人经常使用它时是否值得优化?

【问题讨论】:

  • 当分析显示它在您的应用程序中存在瓶颈时,值得优化,否则不是。
  • 接受的答案确实解释了为什么它更快?
  • 由于接受的答案(和 cmets)详细介绍了同步共享指针计数器的成本,您能否更改您的问题,使其不重复?
  • @UnholySheep 是不是快了两倍几十几百?如果它的速度正好是这个答案中的 100 倍,那么有一些支持数据会很好。
  • shared_ptr 有两个间接级别。一个指向带有原子计数器的数据结构。下一个从那里指向实际对象。移动共享指针涉及第一个指针的简单副本,无需做任何其他事情。引用计数器保持不变,因为引用它的shared_ptrs 的数量没有改变。复制要困难得多:除了复制指针外,还必须(也)以线程安全的方式原子地递增引用计数器。一条原子指令可能需要相当于数千条“非原子”指令的时间。

标签: c++


【解决方案1】:

我写了一个基准。在我的 Macbook Air 上,它快了三倍(g++ 以及 clang++ -std=c++17 -O3 -DNDEBUG)。如果您发现基准测试存在问题,请告诉我。

#include <chrono>
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
using namespace std::chrono;


int COUNT = 50'000'000;

struct TimeIt
{
    system_clock::time_point start;
    TimeIt() {
        start = system_clock::now();
    }
    ~TimeIt() {
        auto runtime = duration_cast<milliseconds>(system_clock::now()-start).count();
        cout << runtime << " ms" << endl;
    }

};

void benchmark_copy(const vector<shared_ptr<int>> &vec_src)
{
    cout << "benchmark_copy" << endl;
    vector<shared_ptr<int>> vec_dst;
    vec_dst.reserve(COUNT);
    TimeIt ti;
    for(auto &sp : vec_src)
        vec_dst.emplace_back(sp);
}
void benchmark_move(vector<shared_ptr<int>> &&vec_src)
{
    cout << "benchmark_move" << endl;
    vector<shared_ptr<int>> vec_dst;
    vec_dst.reserve(COUNT);
    TimeIt ti;
    for(auto &sp : vec_src)
        vec_dst.emplace_back(move(sp));

}

int main (int arg, char **argv){

    vector<shared_ptr<int>> vec;
    for (int i = 0; i < COUNT; ++i)
        vec.emplace_back(new int);

    benchmark_copy(vec);
    benchmark_move(move(vec));

}

【讨论】:

    猜你喜欢
    • 2016-11-27
    • 2012-06-11
    • 2018-02-02
    • 2014-03-25
    • 1970-01-01
    • 2011-09-27
    • 2017-09-15
    • 1970-01-01
    • 2020-07-23
    相关资源
    最近更新 更多