严重高估 Reserve() 是否有负面影响?

2023-11-25

假设我们有一个创建和使用可能非常大的方法vector<foo>是。 已知元素的最大数量为maxElems.

据我所知,C++11 的标准实践是:

vector<foo> fooVec;
fooVec.reserve(maxElems);
//... fill fooVec using emplace_back() / push_back()

但是,如果我们遇到这样一种情况,即在对我们的方法的大多数调用中元素数量显着减少,会发生什么情况?

保守派有什么缺点吗reserve除了多余的分配内存之外的调用(可能可以通过以下方式释放)shrink_to_fit()如果需要的话)?


Summary

很可能有some使用太大储备金的缺点,但多少取决于您的规模和背景reserve()以及您的特定分配器、操作系统及其配置。

您可能知道,在 Windows 和 Linux 等平台上,大型分配通常在首次访问之前不会分配任何物理内存或页表条目,因此您可能会认为大型未使用的分配是“空闲”的。有时这被称为“保留”内存而不“提交”它,我将在这里使用这些术语。

以下是这可能不像您想象的那么免费的一些原因:

页面粒度

上面描述的惰性提交仅发生在页面粒度上。如果您使用(典型的)4096 字节页面,则意味着如果您通常为通常包含占用 100 字节的元素的向量保留 4,000 字节,则惰性提交不会给您带来任何好处!至少必须提交 4096 字节的整个页面,并且不会节省物理内存。因此,重要的不仅仅是预期大小与保留大小之间的比率,而是保留大小的绝对大小决定了您将看到多少浪费。

请记住,许多系统现在都透明地使用“大页面”,因此在某些情况下,粒度将达到 2 MB 或更多。在这种情况下,您需要分配大约 10 或 100 MB 的内存才能真正利用惰性分配策略。

更差的配置表现

C++ 的内存分配器通常会尝试分配大块内存(例如,通过sbrk or mmap在类 Unix 平台上),然后有效地将其分割成应用程序请求的小块。通过系统调用获取这些大块内存,例如mmap可能比分配器内的快速路径分配慢几个数量级,分配器通常只有十几条指令左右。当您请求您通常不会使用的大块时,您就会失败该优化,并且您通常会走上缓慢的道路。

作为一个具体的例子,假设你的分配器要求mmap它划分 128 KB 的块以满足分配。您在典型的情况下分配了大约 2K 的内容vector, but reserve64K。您现在需要支付mmap互相呼唤reserve打电话,但如果你只要求你最终需要的 2K,你会有大约 32times fewer mmap calls.

对过度使用处理的依赖

当您请求大量内存但不使用它时,您可能会遇到这样的情况:您请求的内存超出了系统支持的内存(例如,超出了 RAM + 交换区)。这是否均匀allowed取决于您的操作系统及其配置方式,并且无论您是否准备好一些有趣的行为,如果您随后仅通过写入来提交更多内存。我的意思是任意进程可能会被终止,或者您可能会在任何内存写入时遇到意外错误。由于不同的原因,在一个系统上有效的方法可能在另一个系统上失败过度使用可调参数.

最后,它使管理您的流程变得更加困难,因为监视工具报告的“VM 大小”指标与您的流程最终可能提交的内容没有太大关系。

更糟糕的地方

分配比您需要的更多的内存可能会使您的工作集在虚拟地址空间中分布得更加稀疏。总体效果是参考局部性的减少。对于非常小的分配(例如,几十个字节),这可能会减少同一缓存行内的局部性,但对于较大的大小,主要影响可能是将数据分散到更多的物理页上,从而增加 TLB 压力。确切的阈值很大程度上取决于细节,例如是否启用大页面。

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

严重高估 Reserve() 是否有负面影响? 的相关文章

  • 进入嵌入式[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 忽略父进程中的信号

    我正在尝试实现一个 shell 程序 我希望 shell 程序忽略 SIG INT ctrl c 但在我的程序中 子进程也会忽略 SIG INT 信号 但它不应该这样做 因为 exec 应该将子进程带到另一个程序 并且该程序默认情况下应该处
  • C# SMO 远程数据库备份到本地机器

    我有一个执行 SQL 数据库备份和恢复的应用程序 这在本地计算机上运行良好 但是如果我针对另一台计算机上托管的 SQL 服务器运行此应用程序 则会出现以下错误 Microsoft SqlServer Management Smo Faile
  • 从 C# 访问 COM vtable

    C 中有没有办法访问 COM 对象的虚拟方法表以获取函数的地址 经过大量搜索和拼凑不同的部分解决方案后 我弄清楚了如何做到这一点 首先 您需要为您尝试访问的对象定义 COM 组件类 ComImport Guid InterfaceType
  • 在“delete this;”语句期间发生了什么?

    请考虑以下代码 class foo public foo foo void done delete this private int x 以下两个选项中发生了什么 并且有效吗 选项1 void main foo a new foo a gt
  • Image.FromStream() 方法返回 Invalid Argument 异常

    我正在从智能相机成像器捕获图像 并通过套接字编程从相机接收字节数组 NET 应用程序是客户端 相机是服务器 问题是我在运行时收到 System InvalidArgument 异常 private Image byteArrayToImag
  • C#:如何确定坐标是否在美国大陆?

    我正在获取坐标 纬度 经度 我想检查这些坐标是否位于美国大陆 有没有一种简单的方法可以在 C 中实现 我可以将坐标转换为 MGRS 或 UTM 谢谢 哇哦 他们专门为你准备了 http econym org uk gmap states x
  • 如何转换 UTF-8 <-> UTF16 可移植

    有没有一种简单 可移植的方法 至少是 win32 linux 将 UTF 16 转换为 UTF 8 并返回 最好使用升压 谢谢你的帮助 托比亚斯 Both libiconv http www gnu org software libicon
  • 隐式转换和编译器的不同行为

    Motivated by this question https stackoverflow com q 51972738 5800831 I created the following code struct X X int struct
  • 如何声明返回相同类型的 Func Delegate 的 Func Delegate?

    我想编写一个方法 该方法可以完成一些工作 并最终返回另一个与原始方法具有相同签名的方法 这个想法是根据前一个字节值顺序处理字节流 而不进行递归 通过这样调用它 MyDelegate executeMethod handleFirstByte
  • ASP Net Core 属性路由和双正斜杠

    正如所指出的here https stackoverflow com a 20524044 3129340 URL 中包含双斜杠是有效的 我有一个使用属性路由的 ASP Net Core 项目 一个名为GroupController用于处理
  • IOS Box2D - 身体遵循基于速度波动的点数组的特定路径

    我有一个关于身体的问题 它遵循特定的路径 首先是将身体移动到目标点的方法 const float destinationControl 0 3f b2Vec2 targetPosition path counter b2Vec2 missi
  • 在 C++ 中运行 python [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个用 C 编写的应用程序和一个测试系统 也是用 C 编写的 测试系统非常复杂并且很难改变 我只想做一些小的改变 我的班级是这样的
  • 通过 C++ 标头在 C++ 和 C# 中使用枚举

    我有一个用 C 编写的服务器 位于命名管道的末端 嗯 提供服务 可以发送到服务器的命令在位于头文件中的枚举中定义 enum e doThing1 e doThing2 e doLastThing 所需枚举的值被放入发送到服务器的消息的第一个
  • 如何使用 XmlSerializer 生成标记前缀

    我想使用 XmlSerializer 生成以下内容
  • 偏专业化朋友声明

    在下面的代码中 template
  • TransactionScope 在某些机器上自动升级到 MSDTC?

    在我们的项目中 我们使用 TransactionScope 来确保我们的数据访问层在事务中执行其操作 我们的目标是not要求在我们的最终用户的计算机上启用 MSDTC 服务 问题是 在我们一半的开发人员机器上 我们可以在禁用 MSDTC 的
  • WPF - 将窗口置于前面

    我有一个 WPF 窗口 我没有关闭它 相反 我执行 Hide 和 Show 它 现在 当我双击记录上网格中的主窗口时 这将触发 Show 窗口 该窗口将始终显示在主窗口后面 我尝试过以下方法 但没有成功 view Show view Act
  • 从 C# 应用程序调用 ASP.net Web 服务

    我有个问题 我如何调用 Web 服务并从 C 桌面应用程序获取结果 我正在制作一个桌面应用程序 我希望它能够连接到我的在线 ASP net Web 服务 这怎么可能 在 解决方案资源管理器 中 右键单击项目节点并选择 添加 Service参
  • 布尔实现的atomicCAS

    我想弄清楚是否存在错误答案 https stackoverflow com a 57444538 11248508 现已删除 关于Cuda like的实现atomicCAS for bool是 答案中的代码 重新格式化 static inl

随机推荐