我正在创建一个小型缓存守护进程,我想将其内存使用量限制为大约指定的数量。但是,似乎只是试图计算使用了多少内存。
每次创建CacheEntry对象时,它都会将CacheEntry对象的大小(显然是64字节)加上内部数组中使用的字节数添加到计数器中,以查找正在使用的字节数。删除CacheEntry对象时,它会减去该数量。我可以确认数学,至少是正确的。
但是,在NetBeans中运行时,内存分析器会报告大量不同的数字。大约两倍高,具体而言。它不是内存泄漏,它与当前目前的CacheEntry对象的数量有关。增加内部数组中存储的数据量实际上会使数字更加接近(相反,如果进行了不正确的计算则相反);从这一点,我得出结论,在内存中拥有CacheEntry对象的开销几乎是sizeof()报告的两倍。它不会逐步或“块”上升。
为什么会出现这种情况有一些共同的原因吗?
更新:为了检查,我在没有配置分析器的情况下运行了测试。 Linux报告相同的VmHWM / VmRSS,因此内存分析器肯定不会影响计算。
答案 0 :(得分:0)
也许分析器正在添加引用对象来跟踪对象?在发行版和调试中运行应用程序时,您是否看到相同的结果?
答案 1 :(得分:0)
为什么会出现这种情况有一些共同的原因吗?
是的,这可能是内部碎片和内存管理器的开销。如果您的数据类型很小(例如sizeof(CacheEntry)
是8个字节),new
这样的数据类型可能会产生更大的内存块。它部分用于malloc的内部簿记(它通常存储块的大小),部分用于在自然边界上对齐数据类型所需的填充(例如,8字节数据+ 4字节簿记+ 4字节填充需要将整个事物对齐在8字节边界上。)
您可以通过从单个连续的CacheEntry数组中分配来解决它(例如。CacheEntry array[1000]
只需要1000*sizeof(CacheEntry)
个字节)。您必须跟踪数组中各个元素的使用情况,但这应该是可行的,无需额外的内存。 (例如,通过在免费条目的位置运行条目的自由列表)。
答案 2 :(得分:0)
此内存膨胀是由new
使用引起的,特别是在相对较小的对象上。在Windows上,动态分配的内存每次都会产生16或24字节的开销;我还没有找到Linux的确切数字,但它大致相同。这是因为每个分配的块需要记录其位置和大小(可能不止一次),以便以后可以准确地释放它。
据我所知,正在运行的程序也不确切地知道这涉及多少开销,至少在程序员可以访问的任何方面。
一般来说,大量的小对象应该使用内存池,以保持速度和内存。