【问题标题】:Memory calculation of objects inaccurate?对象的内存计算不准确?
【发布时间】:2012-02-13 16:51:36
【问题描述】:

我正在创建一个小型缓存守护程序,并且我想将其内存使用限制在大约一个指定的量。但是,尝试计算正在使用的内存量似乎存在问题。

每次创建 CacheEntry 对象时,都会将 CacheEntry 对象的大小(显然是 64 字节)加上内部数组中使用的字节数添加到计数器中,以了解正在使用的字节数.当 CacheEntry 对象被删除时,它会减去该数量。我可以确认数学至少是正确的。

但是,当在 NetBeans 中运行时,内存分析器报告大量不同的数字。具体来说,大约是两倍高。这不是内存泄漏,它与 当前 存在的 CacheEntry 对象的数量特别相关。增加存储在内部数组中的数据量实际上使数字更接近(如果计算不正确,则相反,相距更远);由此,我得出结论,在内存中拥有一个 CacheEntry 对象的开销几乎是 sizeof() 报告的两倍。它不会逐步上升或“块”上升。

是否有一些常见的原因导致这种情况发生?

更新:为了检查,我在没有配置分析器的情况下运行了我的测试。无论哪种方式,Linux 都会报告相同的 VmHWM/VmRSS,因此内存分析器肯定不会影响计算。

【问题讨论】:

    标签: c++ memory-management


    【解决方案1】:

    也许分析器正在添加引用对象来跟踪对象?当您在 release 和 Debug 中运行应用程序时,您会看到相同的结果吗?

    【讨论】:

    • 嗯,不错的主意,但在这种情况下,两种方式的用法(和区别)都是相同的。
    • 我很确定尽管分析器通过用自己的调试版本替换 malloc 来帮助分析?
    • 他们很可能 - 但我猜他们也会在内部弥补这一点。如果内存分析首先显着改变了测量的内容,那么它就完全没有用了。
    【解决方案2】:

    是否有一些常见的原因导致这种情况发生?

    是的,这可能是内存管理器的内部碎片和开销。如果您的数据类型很小(例如,sizeof(CacheEntry) 是 8 个字节),newing 这种数据类型可能会产生更大的内存块。它部分用于 malloc 的内部簿记(它通常将块的大小存储在某处),部分用于在其自然边界上对齐数据类型所需的填充(例如,8 字节数据 + 4 字节簿记 + 对齐所需的 4 字节填充整个东西都在 8 字节边界上)。

    您可以通过从 CacheEntry 的单个连续数组中分配来解决它(例如,CacheEntry array[1000] 正好占用 1000*sizeof(CacheEntry) 字节)。您必须跟踪数组中各个元素的使用情况,但这在没有额外内存的情况下应该是可行的。 (例如,通过运行一个空闲条目列表来代替空闲条目)。

    【讨论】:

    • 嗯,这是个问题,因为这个程序依赖于包含大量new 和delete 的双向链表结构。有什么方法可以确切地知道有多少簿记和填充?我不一定需要减少内存使用,只需要跟踪它。
    【解决方案3】:

    这种内存膨胀是由使用new 引起的,特别是在相对较小的对象上。在 Windows 上,动态分配的内存每次都会产生 16 或 24 字节的开销;我还没有找到 Linux 的确切数字,但大致相同。这是因为每个分配的块都需要记录它的位置和大小(可能不止一次),以便以后可以准确地释放它。

    据我所知,正在运行的程序也不知道这涉及到多少开销,至少在程序员可以访问的任何方面都是这样。

    一般来说,大量的小对象应该使用内存池,这既是为了速度,也是为了节省内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      • 2020-11-20
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多