代码之家  ›  专栏  ›  技术社区  ›  deft_code

在c中使用realloc++

  •  15
  • deft_code  · 技术社区  · 15 年前

    std::realloc 如果malloc的内存包含非pod类型,则在c++中是危险的。看来 只有 标准::重新分配 如果类型析构函数不能原位增长内存,则不会调用它。

    一项琐碎的工作 try_realloc 功能。如果不能在原位生成新的内存,那么它将返回false而不是malloc'ing。在这种情况下,可以分配新内存,将对象复制(或移动)到新内存,最后释放旧内存。

    这似乎非常有用。 std::vector
    先发制人阻燃剂: 从技术上讲,这是相同的Big-O性能,但如果矢量增长是应用程序中的一个瓶颈,那么即使Big-O保持不变,x2的速度也很好。

    尝试重新分配 .

    我错过了什么吗?是 没有我想象的那么有用?有什么隐藏的虫子 尝试重新分配 不可用?

    更好的是,是否有一些文档较少的API 是吗?

    注: 尝试重新分配 本质上是一种优化。


    更新: vector 使用realloc会更有效我写了一个概念证明来测试。这个 realloc-vector

    用于比较a 矢量 必须分配19次,同时增长到100万个元素。

    结果,如果 是唯一一个使用堆的东西,结果是可怕的,3-4分配,同时增长到百万字节的大小。

    如果 与 矢量 以66%的速度增长 结果不太乐观,在增长过程中分配了8-10倍。

    最后,如果 与 矢量 重定位矢量 分配17-18次。仅仅比标准向量行为节省了一个分配。

    我不怀疑黑客可以通过游戏分配大小来提高储蓄,但我同意史蒂夫的观点,即编写和维护这样一个分配程序的巨大努力并不能带来收益。

    3 回复  |  直到 15 年前
        1
  •  11
  •   Steve Jessop    15 年前

    vector 通常以大增量增长。如果不重新定位,则不能重复执行此操作,除非您仔细安排,以便在向量的内部缓冲区正上方有很大一部分空闲地址(这实际上需要分配整个页面,因为很明显,以后不能在同一页面上进行其他分配)。

    所以我认为,为了在这里得到一个真正好的优化,你需要的不仅仅是一个“琐碎的解决方法”,如果可能的话,它可以做一个廉价的重新分配-你必须做一些准备 制作 reserve() 他们会变大的。只有当你有一个巨大的地址空间时,你才能对所有的向量自动执行,这样你就可以在每个向量上“浪费”一大块。

    Allocator 概念没有重新分配的功能就是保持它的简单。如果 std::allocator 有一个 try_realloc 标准::分配器 尝试重新分配

    如果 矢量 deque 可能是个不错的替代品。

        2
  •  4
  •   Flexo - Save the data dump sunny moon    15 年前

    try_realloc 你求婚的时候 mmap 具有 MAP_ANONYMOUS 和 MAP_FIXED mremap 具有 MREMAP_FIXED

    编辑 :刚刚注意到,mremap的手册页甚至说:

    计划。mremap()更改 虚拟地址和内存页。这可以用来实现 非常有效率 重新定位(3)。

        3
  •  2
  •   R.. GitHub STOP HELPING ICE    15 年前

    realloc malloc 实现(严格按大小分隔块的实现),因此我认为 重新分配 真是糟糕的做法。

    重新分配 . 这无疑是C++ STL实现使用的方法,所以我认为您的全部关注是毫无根据的。

    编辑 重新分配 实际上,它对于具有虚拟内存的系统上的巨型块非常有用,其中C库与内核交互以将整个页面重新定位到新地址。我说这是很少见的原因是因为你需要处理非常大的块(至少几百KB),否则大多数实现甚至会进入处理页面粒度分配的领域,并且在进入和退出KNEL空间重新排列虚拟内存之前,可能要大得多(几MB)。做拷贝。当然 try_realloc 在这里没有用,因为所有的好处都来自 移动