如何实现自定义 pmr 分配器的完全去虚拟化?

2024-01-04

比较以下使用 C++ 多态内存源的项目的编译草案。为了看看发生了什么,我覆盖了std::pmr::monotonic_buffer_resource与我的 LoggingResource:

LiveDemo https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIAGwapK4AMngMmAByPgBGmMQgABykAA6oCoRODB7evgFBaRmOAmER0SxxCcl2mA5ZQgRMxAQ5Pn6Btpj2xQwNTQSlUbHxSbaNza15HQrjA%2BFDFSOJAJS2qF7EyOwc5gDM4cjeWADUJrtuAG61RMRn2CYaAIJ7B0eYp%2BdsLCQAngD6xEwCnWm0wdwezzM%2BwYhy8JzObiaxCYP3BTxeMLeHzcyBm%2BFQaOeTxmxC8DmOKRYxD%2BTAA7k1MH80IImPNbuiAOxWJ7HXnHLwZIzHMS0VCiG5/Ag/FLvM4AEWOeJAIEpCRVnh%2B32IKQQeGQNNoovFJARSpAMR%2BBDBu3uu25RMefOOAHoAFTHBwkBTHV3OiEQp3O53HLBUJheWgEAN81U0%2BmApmyVkRYgQZbHEAUqlxhmJllskxckVipgSqUywtWDlywsKyu1l3BrD0YCl95EYVMD0CElkm7%2Bnl8zCqFK0PWELPUum55mNNkQZkzYWGktl6XvYvIZbRp28zMkv4QcxmAASXVFx1FQpJ4WAYHvD%2BPpGXRvT9cHu4pxHCBCoR7MZihuGkbdgwvaesQHoipg6D3iYACsbgMMe252jupzVgOjp8kG3YpKiH6NpOOYJrOybxAuPYEMR06kUmBZmP4b67AqQERlGaHooRsa0YyZHzou1E8fGfH0Sm5j%2BMcqAEAg8TPpupYkJK64vmKHx1lytZvoRTr7gQ1IQNJsnEAAdAe8krluGH2p%2BvIpN%2Bgh/seHj4aB4E3FBhowXBiHIQBqE2XytZYYGwbfFc6HCTOYkUVFdH5uJjESVJMnxOmDCoMOWwpFGOl8np1KVma4WYIZqWmQeqwpcZJnAJgBAGkaimpm%2BmGEe%2B2GfvZP5OQBkSZao2XUSVbn6X2JCefQsFgAhSEoWcgW8sFXGdTRIl5nOKYQHFokJfEEnJUZcmjapxrUuWYKMad255Xuir6YexWoFcZU1ZVFmvuhHW2V%2BPX/mYQgysgeA0MgxwjYJpIQZN3kzb582caty0OqFwoKBkwARGwgghTG2a8Rt5G3FdqAysi/YsZRYFCfj638YlknEAgCjMaxmBhuxC2RbT0V7cTkmk/EzXyttPPxZt%2B1JVdTMs%2BpIbs8BHH2uhAB%2BO2E/OrPyxzkZcytToKWuMrHHVDWGyQaYnd9tmAgQGwMPd1K1fVjWrhbAVfW1KN8maqrKje14PXLx5niul4CMAju3g%2Bj4AXrzyYYjWGHEw6PHCEqDAMAt4AEpAiCWwZhSXgxGOYO%2B1SypfL8AL5xsWz%2BppTwpCXZcgOhGdZ7ndeghAFdqtXxD/ICwL1%2B8rpeAwWDELQPy3rXo%2BgummaT9Ps/zyPBeMpWq/xOvRgL1vDaVhhNYrd1Fxtu3hEXKgeDoD66CoK74qlRkABejLURaVoKM%2BH9f2XHgTG6ZnrxG/PCJuq0nTdUcv9R4llSy3lOGYeCD8f5Ah8nNACz4MEs3jj9W29t%2BRTz3nPA%2Bm8x5/AALR3ENqVPBFlgEMA9u1L26Fb73xDM/LA9CICcPQK6FI/88Cf0lMcRhipRGALEMw1qi1dy7xnuQ4Ah8qG0JtLwxBVptq4MtECJhICCFBXYYRGIqBPDcL%2BHgBQfxMAAEcvBiD7gQdAyo/YgEHsPHuhdBKHXKumQSxwMpZUwDlKSVxiAQNlFAwh9ViFKP3qoyhoIaF3BsXYxxzijrEFYUjUxq1%2B5V0wFqbxi8tjukSSotRqT47BSTk8H84Nkxpkbgos0SIUSmlccqDBz4zAaDMJIO4EivBUGMbyIpniBDSQEHqP4MQxlUHiDUwuFQFCVkWVQEy6BSxMDTLgsZZlpGtMTsrQinds5GDzuU94opkk%2BLBJpRi6z6nnMKT0lUlcQBXAggidW9N9o2mOBcE%2BJ8AUxVuFyFB/h7mrKeXKZ8EK%2BZgsYnClJDdqyn2fBJdFjy3mNzlBwVYtBODwV4H4DgWhSCoE4G4aw1hFRbxQbsHgpACCaGJasAA1iAeCkgTL%2BDMFIDQABOUVwr/Aci4IM/QnBJAUs5TSzgvAFAgCCByqlxLSBwFgDARAKBUAsBSHQOSFBKLGtNQkYAoquB8DoFaYgaqIAxCVTEcITQficDZWgFg2MCAAHkGCzyVVgFghhgDiC1aQfAgI6hXDVdG4ctQvBWiVT%2BLoSqxwxGREPDwWAlX6TwCwb12qqAGGAAoAAangTAtIA0ykpWy/gggRBiHYFIGQghFAqHUNG3QdqDBGBQAyyw%2Bg8AxDVZAVYpMeiJuodQvE8pTCWGsFwDkxxqEBrMKqro1wsguCnpMPwiR4LBCnoMcolQQBmA5KK1I6RMgCGPXoQoT6GCXuGAkRi0gah1AEH0CYng2hJDPX%2BnogG5hlC/Teu9Yx%2BgvrtTMfon7Fjfv8JIVYty9D6UwNsHgJKyWKujbSjgqhEj%2BGoRhk2yAwaipMlwY4EB6WrrHccXAhAJp7DtccDwlr6CQW48sXgmqtDLB5XyoIpKOAKtICWyQuwTK7HghyXY/hlOSFvbsUVkgz2UupaR1V6r2WctWLqg16wCAtwIOQSgvqTUCciKwbY5HKPUZTkKCAY0GDcuE8EfANx756BbcIUQ4hO0hZ7WoJVA7SC0mRCkUthGODktIPp3gpGA2pus1JKgxxXNUckDRujDGmN8Yc/EFlXA/Oia5aQWSTBp6UGS7Jkt8F/CCs0%2BpjDKnGIaHgnppVhnbDGdq%2BJ0gvLdNKY5Ke0VGgNAzd2GYRIorkjSd2MRgzKqTNavG9JndaWhvbbG6sSJGRnCSCAA%3D

#include <vector>
#include <memory_resource>
#include <array>
#include <cstdio>

struct pmr_aware_container
{
    using allocator_type = std::pmr::polymorphic_allocator<std::byte>;

    /* ctors */

    // default
    pmr_aware_container() : pmr_aware_container{allocator_type{}} {} // delegate to aa constructor

    explicit pmr_aware_container(const allocator_type alloc)
        : str_("Hello long string!!!", alloc) {
        printf("default constructor called!\n");
    }

    // copy
    // pmr_aware_container(const pmr_aware_container&) = default;

    pmr_aware_container(const pmr_aware_container& other, allocator_type alloc = {}) 
        : str_(other.str_, alloc) {
        printf("Copy constructor called!\n");
    }

    // move
    pmr_aware_container(pmr_aware_container&& other) noexcept
        : str_{std::move(other.str_), other.get_allocator() }
    {
        printf("Noexcept move constructor called!\n");
    }

    pmr_aware_container(pmr_aware_container&& other, const allocator_type& alloc)
        : str_(std::move(other.str_), alloc)
    {
        printf("Specific move constructor called!\n");
    }

    // assignement

    pmr_aware_container& operator=(const pmr_aware_container& rhs) = default;
    pmr_aware_container& operator=(pmr_aware_container&& rhs) = default;

    ~pmr_aware_container() = default;

    allocator_type get_allocator() const {
        return str_.get_allocator();
    }

    std::pmr::string str_ = "Hello long string!!!";
};


class LoggingResource : public std::pmr::memory_resource
{
public:
    LoggingResource(std::pmr::memory_resource *underlying_resource) : underlying_resource_{underlying_resource} { }

private:
    void *do_allocate(size_t bytes, size_t align) override {
        printf("Allocating %d bytes!\n", bytes);
        return underlying_resource_->allocate(bytes, align);
    }

    void do_deallocate(void*p, size_t bytes, size_t align) {
        underlying_resource_->deallocate(p, bytes, align);
    }

    bool do_is_equal(std::pmr::memory_resource const& other) const noexcept override {
        return underlying_resource_->is_equal(other);
    }

    std::pmr::memory_resource* underlying_resource_;
};

int main()
{
    std::array<std::byte, 2024> buf;
    std::pmr::monotonic_buffer_resource mbs{buf.data(), buf.size()};

    LoggingResource log_resource{&mbs};

    std::pmr::vector<pmr_aware_container> v{ { pmr_aware_container{ &log_resource}, pmr_aware_container{ &log_resource} }, &log_resource};
}

检查二进制文件后,我非常惊讶地发现,即使使用最新的编译器 gcc 12.1,我的 LoggingResource 所做的虚拟调用实际上也没有被虚拟化。我认为这种情况会发生,因为 pmr 的速度必须像广告中宣传的那样快。这是程序集中各自的 vtable:

vtable for LoggingResource:
        .quad   0
        .quad   typeinfo for LoggingResource
        .quad   LoggingResource::~LoggingResource() [complete object destructor]
        .quad   LoggingResource::~LoggingResource() [deleting destructor]
        .quad   LoggingResource::do_allocate(unsigned long, unsigned long)
        .quad   LoggingResource::do_deallocate(void*, unsigned long, unsigned long)
        .quad   LoggingResource::do_is_equal(std::pmr::memory_resource const&) const

我可以看到从 gcc 9.1 到 12.1 有了改进,当时甚至连单调缓冲区资源都没有去虚拟化。 gcc 9.1 的输出:

vtable for std::pmr::monotonic_buffer_resource:
        .quad   0
        .quad   typeinfo for std::pmr::monotonic_buffer_resource
        .quad   std::pmr::monotonic_buffer_resource::~monotonic_buffer_resource() [complete object destructor]
        .quad   std::pmr::monotonic_buffer_resource::~monotonic_buffer_resource() [deleting destructor]
        .quad   std::pmr::monotonic_buffer_resource::do_allocate(unsigned long, unsigned long)
        .quad   std::pmr::monotonic_buffer_resource::do_deallocate(void*, unsigned long, unsigned long)
        .quad   std::pmr::monotonic_buffer_resource::do_is_equal(std::pmr::memory_resource const&) const
vtable for LoggingResource:
        .quad   0
        .quad   typeinfo for LoggingResource
        .quad   LoggingResource::~LoggingResource() [complete object destructor]
        .quad   LoggingResource::~LoggingResource() [deleting destructor]
        .quad   LoggingResource::do_allocate(unsigned long, unsigned long)
        .quad   LoggingResource::do_deallocate(void*, unsigned long, unsigned long)
        .quad   LoggingResource::do_is_equal(std::pmr::memory_resource const&) const

如果我尝试嵌套不同的内存分配器(例如单调缓冲区资源上的池分配器等),这可能证明性能至关重要。但是,让我好奇的是std::monotonic_buffer_resource did实际上去虚拟化。这怎么可能?我怎样才能为我的分配器实现同样的目标?


None

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

如何实现自定义 pmr 分配器的完全去虚拟化? 的相关文章

  • 谁能建议我一种在 C++ 中分割名称的简单方法

    我一直在尝试将名称分为名字和姓氏 但我确信我的实现就简单性而言并不是最好的 string name John Smith string first string last name name find getting lastname fo
  • 使用 mono/nunit-console/4 在 Mac OS X 控制台上运行测试

    我安装了 Max OS X 10 11 1 上面装有 Xamarin 我编写了简单的测试类 只是为了测试在 Mac OS X 和 Ubuntu 上运行 Nunit 测试 该类实际上有一个返回字符串的方法 using System names
  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • 给出 5 个参数,但在终端中只得到 3 个参数

    我想将一个文件传递给一个c 程序 如果我在 IDE 中执行此操作 test string string lt test txt return argc 5 但在终端上我刚刚得到argc 3 看来 这是因为 什么是 lt 意思是 我正在使用
  • 运行选定的代码生成器时出错:“未将对象引用设置到对象的实例。”错误?

    我已经尝试了所有解决方案 例如修复 VS 2013 但没有用 当您通过右键单击控制器文件夹来创建控制器并添加控制器时 然后右键单击新创建的控制器的操作并选择添加视图 当我尝试创建视图时 就会发生这种情况 它不是一个新项目 而是一个现有项目
  • C# 中的 strstr() 等效项

    我有两个byte 我想找到第二个的第一次出现byte 在第一个byte 或其中的一个范围 我不想使用字符串来提高效率 翻译第一个byte to a string会效率低下 基本上我相信就是这样strstr 在 C 中做 最好的方法是什么 这
  • 在 EnvDTE 中调试时捕获 VS 局部变量

    是否可以使用 EnvDTE 进行 vsix Visual Studio 扩展来捕获本地和调试窗口使用的调试数据 或者可以通过其他方法吗 我想创建一个自定义的本地窗口 我们可以修改它以根据需要显示一些较重的内容 而无需为高级用户牺牲原始的本地
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 跨多个域的 ASP.NET 会话

    是否有合适的 NET 解决方案来在多个域上提供持久服务器会话 即 如果该网站的用户在 www site1 com 下登录 他们也将在 www site2 com 下登录 安全是我们正在开发的程序的一个问题 Thanks 它是否需要在会话中
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • 如何在 DropDownList 中保留空格 - ASP.net MVC Razor 视图

    我在视图中通过以下方式绑定我的模型 问题是我的项目文本是格式化文本 单词之间有空格 如下所示 123 First 234 00 123 AnotherItem 234 00 123 Second 234 00 我想保留此项目文本中的空格 即
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte

随机推荐

  • 导出或保存 CX509PrivateKey

    是否可以以某种方式保存或导出CX509PrivateKey 我的想法是 我创建一个 CSR 发送给 CA 获取证书 然后 不知何故我必须获取私钥 但不知道如何获取 不幸的是在谷歌上没有找到任何内容 我的一段代码 var objPrivate
  • SQL INSERT 不指定列。会发生什么?

    在浏览心爱的 W3schools 时发现了这个page http www w3schools com sql sql insert asp并且实际上学到了一些有趣的东西 我不知道您可以调用插入命令而不指定值的列 例如 INSERT INTO
  • 使用jquery删除字符串中的span标签

    如何使用jquery从字符串中删除span标签 我在字符串变量中有多个跨度标签 p No Change span style color 222222 nbsp span I love cricket span style color 22
  • 满足条件后避免使用 IF 语句

    我在一个重复多次的循环内进行除法运算 碰巧的是 在循环的前几次 或多或少的前 10 个循环 中 除数为零 一旦它获得价值 除零误差就不再可能 我有一个if测试除数值的条件以避免 div 为零 但我想知道评估此值会对性能产生影响if在后续循环
  • Android 开发人员通常在 iPhone 上使用第三方 UI/网络库(例如 Three20)吗?

    我做过很多 iPhone 方面的工作 但从来没有做过 Android 方面的工作 在 iPhone 上 几个月后我发现了 Three20 库 非常棒 并开始移动我的代码 我不想在转向 Android 时犯同样的错误 所以我的问题是 Andr
  • Scala 2.10 TypeTag 用法

    我正在挖掘新的 scala 反射 api 但无法弄清楚为什么以下代码片段不能按预期工作 给定层次结构 尽力简化 import scala reflect runtime universe trait TF A implicit def t
  • 任务并行性 - 任务 OnCompleted 在所有ContinueWith之后触发

    我在处理任务时遇到问题 GetAwaiter OnCompleted new Action 我有一个带有多个ContinueWith的主任务 但是当我返回主任务并在OnCompleted上添加委托时 它会在处理主任务后触发 而不是在所有Co
  • 每个循环使用 Rspec 的单元测试用例

    我的模型中有以下方法 def get performance data para child para hash performance graph data child para hash each do cp performance g
  • onclick 事件传递
  • id 或值
  • 我想通过 li id or value in onclick事件 这是我的退出代码 li li value 1 li li value 2 li 这是 JavaScript 代码 function getPaging str loading
  • SSL/TLS 中的相互身份验证

    我是 SSL 身份验证的新手 我需要使用 SSL 在信任边界上对两个架构组件进行身份验证 我可以控制这两个组件 我想我需要两种方式的 SSL 身份验证 服务器和客户端都有证书 证书可以自签名吗 即由供应商签名 这不会首先使使用 SSL 无效
  • jqgrid客户端排序desc/asc

    我已经看到了这个问题的许多变体 并且我尝试使用所有知识 但仍然没有运气 我的日期正在从旧到新排序 我想将它们从新到旧排序 在你看到 desc 的地方 我尝试过 asc 但没有改变 当我尝试分页时 它似乎触发了重新加载 并且排序是正确的 从新
  • 如何找出与矩阵的特定特征值相对应的特征向量?

    如何找出与特定特征值对应的特征向量 我有一个随机矩阵 P 其特征值之一是1 我需要找到与特征值1对应的特征向量 scipy 函数scipy linalg eig http docs scipy org doc scipy reference
  • 如何为 TextView 文本添加下划线并更改下划线的颜色

    我想为文本视图文本添加下划线并将下划线的颜色更改为蓝色 我已经这样做了 但我的代码正在更改文本视图和下划线的颜色 我只想更改下划线的颜色 我们应该怎么做 TextView tv TextView findViewById R id tv S
  • Swing GridBagLayout 组件调整大小

    我正在开发一个项目 我的目标是使组件根据窗口的大小调整大小 我在用GridBagLayout为此 但是在窗口大小调整时调整组件大小时我遇到了一些问题 当我给出我的组件时weighty值 一切都很好 组件垂直调整大小 http imagesh
  • 如何格式化 SQLAlchemy ORM Postgresql CIDR contains (>>) 查询

    我有一个定义的模型 from app import db from sqlalchemy dialects import postgresql class TableIpAddress db Model tablename ipaddres
  • [Statsmodels]:如何让 statsmodel 返回 OLS 对象的 pvalue?

    我对编程还很陌生 我正在尝试使用 Python 来熟悉数据分析和机器学习 我正在学习有关多元线性回归的向后消除的教程 这是现在的代码 Importing the libraries import numpy as np import mat
  • Android 4.x RemoteControlClient.setTransportControlFlags() 不起作用?

    我正在尝试使用 RemoteControlClient 类来支持我的应用程序的锁屏播放器 一个问题是设置传输控制标志似乎无法正常工作 例如 我试图只显示播放 停止图标 而不显示上一个 下一个 mRemoteControlClient set
  • Terracotta Cluster 仍然开源吗?

    如果是的话 在哪里可以找到它 根据this http www infoq com news 2006 12 terracotta jvm clusteringinfoq条目 他们已经开源了 但目前他们的网站上还没有这样的产品 这一页 htt
  • 在 Python shell 和 *.py 文件中运行时 Python 不同的内存管理行为

    示例1 tmp cat t py a 250000000000 b 250000000000 print id a id b id a id b tmp python t py 140450848587992 140450848587992
  • 如何实现自定义 pmr 分配器的完全去虚拟化?

    比较以下使用 C 多态内存源的项目的编译草案 为了看看发生了什么 我覆盖了std pmr monotonic buffer resource与我的 LoggingResource LiveDemo https godbolt org z O