为什么通过weak_ptr调用这么慢?

2024-01-06

我已阅读问题weak_ptr 的性能损失是什么? https://stackoverflow.com/questions/2748091/whats-the-performance-penalty-of-weak-ptr但我自己的测试显示出不同的结果。

我正在用智能指针创建代表。下面的简单代码重现了性能问题weak_ptr。有人能告诉我为什么吗?

#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
#include <stdint.h>
#include <string>
#include <utility>

struct Foo
{
    Foo() : counter(0) { incrStep = 1;}

    void bar()
    {
        counter += incrStep;
    }

    virtual ~Foo()
    {
        std::cout << "End " << counter << std::endl;
    }
private:
    uint64_t counter;
    uint64_t incrStep;
};

void pf(const std::string &md, const std::function<void()> &g)
{
    const auto st = std::chrono::high_resolution_clock::now();
    g();
    const auto ft = std::chrono::high_resolution_clock::now();
    const auto del = std::chrono::duration_cast<std::chrono::milliseconds>(ft - st);
    std::cout << md << " \t: \t" << del.count() << std::endl;
}

和测试:

int main(int , char** )
{
    volatile size_t l = 1000000000ULL;
    size_t maxCounter = l;

    auto a = std::make_shared<Foo>();
    std::weak_ptr<Foo> wp = a;

    pf("call via raw ptr        ", [=](){
        for (size_t i = 0; i < maxCounter; ++i)
        {
            auto p = a.get();
            if (p)
            {
                p->bar();
            }
        }
    });

    pf("call via shared_ptr      ", [=](){
        for (size_t i = 0; i < maxCounter; ++i)
        {
            if (a)
            {
                a->bar();
            }
        }
    });

    pf("call via weak_ptr       ", [=](){
        std::shared_ptr<Foo> p;
        for (size_t i = 0; i < maxCounter; ++i)
        {
            p = wp.lock();
            if (p)
            {
                p->bar();
            }
        }
    });

    pf("call via shared_ptr copy", [=](){
        volatile std::shared_ptr<Foo> p1 = a;
        std::shared_ptr<Foo> p;
        for (size_t i = 0; i < maxCounter; ++i)
        {
            p = const_cast<std::shared_ptr<Foo>& >(p1);
            if (p)
            {
                p->bar();
            }
        }
    });

    pf("call via mem_fn         ", [=](){
        auto fff = std::mem_fn(&Foo::bar);
        for (size_t i = 0; i < maxCounter; ++i)
        {
            fff(a.get());
        }
    });

    return 0;
}

Results:

$ ./test
call via raw ptr            :   369
call via shared_ptr         :   302
call via weak_ptr           :   22663
call via shared_ptr copy    :   2171
call via mem_fn             :   2124
End 5000000000

如你看到的,weak_ptr慢 10 倍shared_ptr与复制和std::mem_fn比使用原始 ptr 或慢 60 倍shared_ptr.get()


在尝试重现您的测试时,我意识到优化器可能会消除比应有的更多的东西。我所做的是利用随机数来击败过度优化,这些结果看起来很现实std::weak_ptr比慢近三倍std::shared_ptr or its 原始指针.

我在每个测试中计算校验和,以确保它们都在做相同的工作:

#include <chrono>
#include <memory>
#include <random>
#include <vector>
#include <iomanip>
#include <iostream>

#define OUT(m) do{std::cout << m << '\n';}while(0)

class Timer
{
    using clock = std::chrono::steady_clock;
    using microseconds = std::chrono::microseconds;

    clock::time_point tsb;
    clock::time_point tse;

public:

    void start() { tsb = clock::now(); }
    void stop()  { tse = clock::now(); }
    void clear() { tsb = tse; }

    friend std::ostream& operator<<(std::ostream& o, const Timer& timer)
    {
        return o << timer.secs();
    }

    // return time difference in seconds
    double secs() const
    {
        if(tse <= tsb)
            return 0.0;

        auto d = std::chrono::duration_cast<microseconds>(tse - tsb);

        return double(d.count()) / 1000000.0;
    }
};

constexpr auto N = 100000000U;

int main()
{
    std::mt19937 rnd{std::random_device{}()};
    std::uniform_int_distribution<int> pick{0, 100};

    std::vector<int> random_ints;
    for(auto i = 0U; i < 1024; ++i)
        random_ints.push_back(pick(rnd));

    std::shared_ptr<int> sptr = std::make_shared<int>(std::rand() % 100);
    int* rptr = sptr.get();
    std::weak_ptr<int> wptr = sptr;

    Timer timer;

    unsigned sum = 0;

    sum = 0;
    timer.start();
    for(auto i = 0U; i < N; ++i)
    {
        sum += random_ints[i % random_ints.size()] * *sptr;
    }
    timer.stop();

    OUT("sptr: " << sum << " " << timer);

    sum = 0;
    timer.start();
    for(auto i = 0U; i < N; ++i)
    {
        sum += random_ints[i % random_ints.size()] * *rptr;
    }
    timer.stop();

    OUT("rptr: " << sum << " " << timer);

    sum = 0;
    timer.start();
    for(auto i = 0U; i < N; ++i)
    {
        sum += random_ints[i % random_ints.size()] * *wptr.lock();
    }
    timer.stop();

    OUT("wptr: " << sum << " " << timer);
}

编译器标志:

g++ -std=c++14 -O3 -g0 -D NDEBUG -o bin/timecpp src/timecpp.cpp

示例输出:

sptr: 1367265700 1.26869 // shared pointer
rptr: 1367265700 1.26435 // raw pointer
wptr: 1367265700 2.99008 // weak pointer
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么通过weak_ptr调用这么慢? 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 用于选择特定 div 中具有特定类的锚元素的 jQuery 选择器是什么

    我有一些这样的代码 我想选择每个 a 带有类的标签status在 div 中foo div a class status a div 你可以这样做 foo find status a
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 在线条末端绘制标签

    我有以下数据 temp dat完整数据请参见尾注 Year State Capex 1 2003 VIC 5 356415 2 2004 VIC 5 765232 3 2005 VIC 5 247276 4 2006 VIC 5 57988
  • 在 SQL 查询中显示串联值

    我想将我的第一个 sql 查询与下面显示的 id pr 值的表类型连接起来 ID PR 值会重复 我想显示 ident st 列中与相同 id pr 和 rodz st 值用逗号分隔符连接的所有值 例如 显示 rodz st DZE 和 i
  • 在 MATLAB 中交换两个元素的性能

    纯粹作为实验 我在 MATLAB 中编写排序函数 然后通过 MATLAB 分析器运行这些函数 我发现最令人困惑的方面是与交换元素有关 我发现交换矩阵中两个元素的 官方 方式 self Data i1 i2 self Data i2 i1 运
  • 对于 Electron 来说,结合 Node.js 和 Chromium 上下文意味着什么?

    In 一篇博文 http maxogden com electron fundamentals html作者提到 Electron 将 Node 和 Chromium 组合成一个 单一上下文 这意味着我们不必使用 Browserify 来转
  • SqlBulkCopy 和实体框架

    我当前的项目由 3 个标准层组成 数据 业务和表示 我想使用数据实体来满足我的所有数据访问需求 该应用程序的部分功能是需要将平面文件中的所有数据复制到数据库中 文件不是很大 所以我可以使用 SqlBulkCopy 我发现了几篇关于 NET
  • android 使用 .der 公钥验证文件签名

    我正在尝试验证文件的签名 我按照以下说明生成证书 generate a private key with size of 2048 bits openssl genrsa out private key pem 2048 derive a
  • 我如何通过 sql server 2008 中的 XP_CMDSHELL 通过网络访问文件/文件夹?

    我正在尝试使用 EXEC MASTER XP CMDSHELL 访问文件夹 目录 它适用于本地文件 文件夹 但它无法通过网络访问该文件夹 EXEC MASTER XP CMDSHELL c Images Works fine EXEC MA
  • 如何使用 9 切片在 WPF 中叠加两个图像?

    我将展示一些 脏 代码 我不完全理解这些代码 因为我是 C 新手 根据我的理解 任何要绘制的控件都会被分成9个矩形 然后通过设置来单独绘制每个矩形Fill矩形的属性 我将隐藏每个矩形的代码 以保持代码的可管理大小 但是 我希望您明白该函数试
  • Google Cloud Datastore JSON API 的 datasetId 是什么

    正如中提到的this https stackoverflow com questions 25097451 how do i find my datasetid for making google datastore queries ans
  • 以编程方式构建 msbuild 15 项目

    我正在尝试构建一个使用 VS2017 创建的简单 C 7 类库项目 框架程序集的 MSBuild 已经过时了 所以我引用Microsoft Build Microsoft Build Engine and Microsoft Build F
  • 当按下回车键时如何转到下一个文本框?

    大家好 我正在学习 Javascript 我想问你们 当我按下键盘上的 Enter 按钮输入文本后 如何才能转到下一个文本框 谢谢 您可以使用 keyup 跟踪用户何时完成字符输入并e keyCode获取按下了哪个键 如果是 13 意味着进
  • 如何提高这段代码的性能呢?

    我正在尝试学习一些 Julia 在阅读了几个小时的手册后 我编写了以下代码 ie 200 ez zeros ie 1 hy zeros ie fdtd1d steps for n in 1 steps for i in 2 ie ez i
  • Doxygen:是否可以控制依赖图的方向?

    Up until today I d been using an ancient version 1 4 7 of doxygen dot and it typically drew graphs with a vertical orien
  • 比较 Msbuild 中的日期时间戳

    我正在尝试比较 msbuild 中的两个日期时间戳 我做了以下事情
  • Visual C++ __forceinline 奇怪的行为

    我试图强制 Visual C 编译器内联特定函数 我知道inline or forceinline只是一个建议 根据MSDN https msdn microsoft com en us library bw1hbe6y aspx 如果编译
  • 如何正确使用MouseMotionListener来按下JButtons?

    我制作了一个小型康威生命游戏程序 我已经完成了大约 80 我用过一个网格JButtons作为细胞 现在我有一个ButtonListener在每个按钮上 因此您必须通过单击各个按钮来逐一绘制您想要的图案 我希望能够快速单击并拖动鼠标并选择按钮
  • request.is_ajax() == 点击后退按钮时为 True?

    我有一个 Django 应用程序 它根据页面请求是否为 Ajax 返回不同的响应 当我查看页面 导航到其他地方 然后单击后退按钮时 请求将被呈现为就像request is ajax 是真的 因此 JSON 输出显示在浏览器中 而不是生成的
  • python 获取 json 键作为完整路径

    我想解析一个 JSON 文件并获取包含访问密钥所需的所有路径的完整列表 如果我们使用keys方法 我们会得到单个键的列表 但不会得到访问数据所需的分层键的完整列表 所以如果给定数据这样 data glossary title example
  • Elm 与 ClojureScript 相比如何?

    我已经到了这样的地步 使用 Backbone js 面向对象的 MVC 模式进行 GUI 编码变得非常复杂 并且正在考虑其他范例 MDV https github com Polymer TemplateBinding FRP http e
  • 为什么通过weak_ptr调用这么慢?

    我已阅读问题weak ptr 的性能损失是什么 https stackoverflow com questions 2748091 whats the performance penalty of weak ptr但我自己的测试显示出不同的