【问题标题】:Why make_shared slower than shared_ptr<T>( new T)为什么 make_shared 比 shared_ptr<T>(new T) 慢
【发布时间】:2019-11-26 06:56:25
【问题描述】:

在每篇文章中都写到make_sharedshared_ptr&lt;T&gt;(new T) 更有效,因为分配了一个内存而不是两个。但我试试这段代码:

#include <cstdio>
#include <ctime>

#include <memory>
#include <vector>

static const size_t N = 1L << 25;

int main(void) {

    clock_t start = clock();
        for ( size_t rcx = 0; rcx < N; rcx++ ) {
            auto tmp = std::shared_ptr<std::vector<size_t>>( new std::vector<size_t>( 1024 ) );
        }
    clock_t end = clock();
    printf("shared_ptr with new: %lf\n", ((double)end - start) / CLOCKS_PER_SEC);

    start = clock();
        for ( size_t rcx = 0; rcx < N; rcx++ ) {
            auto tmp = std::make_shared<std::vector<size_t>>( 1024 );
        }
    end = clock();
    printf("make_shared: %lf\n", ((double)end - start) / CLOCKS_PER_SEC);

    return 0;
}

编译:

g++ --std=c++14 -O2 test.cpp -o test

得到了这个结果:

shared_ptr with new: 10.502945

make_shared: 18.581738

boost::shared_ptr 也一样:

shared_ptr with new: 10.778537

make_shared: 18.962444

This question 回答了 LLVM 的 libc++ 已损坏,但我使用 GNU 的 libstdc++。 那么,为什么make_shared 慢?

附:用-O3优化得到了这个结果:

shared_ptr with new: 5.482464

make_shared:4.249722

boost::shared_ptr 也一样。

【问题讨论】:

  • “更高效”并不总是意味着“更快”。
  • 我运行你的代码,make_shared 在 Linux 服务器上使用 -O2-O3 更快。您的 GCC、libstdc++ 和 glibc 的架构、操作系统和版本是什么?
  • 使用 msvc make_shared 也更快。我得到 shared_ptr with new: 12.624000 make_shared: 10.969000 release/x64/cl 版本 19.23.28106.4 --- 使用 release/x86 它更快:shared_ptr with new: 10.610000 make_shared: 7.620000
  • 你试过让make_shared循环在new循环之前运行吗?

标签: c++ performance shared-ptr make-shared


【解决方案1】:

在一台计算机上运行程序并测量执行时间通常不会提供有关程序性能的任何信息,而只是在实际条件下在您的设备上提供的信息。 例如,您的操作系统、编译器、设备上运行的其他程序、库版本甚至您的用户名都存在依赖关系。
由于您的程序确实访问了主内存,因此在您的特殊情况下,程序的结构可能使其访问内存更加“快速”。但当然,如果您终止或启动其他软件、更改您的用户或操作系统重组主内存,“性能”看起来完全不同。
因此,如果您想要可靠的数据,您应该至少在不同的设备和不同的条件下运行该程序。但我建议您看一下“分析器”-软件。

【讨论】:

  • 它对内存的实际结构有影响。
  • 你提到的大多数事情应该对正在比较的两个版本产生大致相同的影响
  • 不一定,取决于处理器需要将不同的行加载到其缓存中的内存结构。因此,您完全有可能在不同的用户或另一个系统上运行相同的程序并获得不同的结果。
【解决方案2】:

在您的平台上,std::vector 可能对其分配器进行了优化。请记住,这里实际上有三个可能的分配,而不是两个。有共享控件对象、矢量对象本身以及初始 1,024 个size_t 对象的空间。

使用make_shared,您将失去利用该优化的机会,因为共享控制结构和向量是同时创建的。这是一个不寻常的边缘情况,您可能会发现在其他对象和其他使用模式中看不到这种情况。

您看到的效果可能非常脆弱。在其他库、其他平台、其他对象、其他矢量大小等情况下,您可能看不到它。

您发现了一种奇怪的边缘情况,通常的建议碰巧会产生稍慢的结果。

【讨论】:

  • 我第一次尝试使用 std::string,而不是 std::vector。我使用大字符串来禁用小字符串优化。
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 2017-03-19
  • 2014-07-09
  • 2015-04-21
相关资源
最近更新 更多