这是我最后一个问题的延续。我无法理解向量占用的内存。问题骨架:
考虑一个向量,它是列表的集合,而列表是指针的集合。就像:
std::vector<std::list<ABC*> > vec;
Run Code Online (Sandbox Code Playgroud)
ABC是我的班级。我们在64位计算机上工作,因此指针的大小为8个字节。
在项目流程的开始,我将此向量的大小调整为一个数字,以便可以将列表存储在各个索引处。
vec.resize(613284686);
Run Code Online (Sandbox Code Playgroud)
此时,向量的容量和大小将为613284686。对。调整大小后,我将列表插入相应的索引为:
// Some where down in the program, make these lists. Simple push for now.
std::list<ABC*> l1;
l1.push_back(<pointer_to_class_ABC>);
l1.push_back(<pointer_to_class_ABC>);
// Copy the list at location
setInfo(613284686, l1);
void setInfo(uint64_t index, std::list<ABC*> list>) {
std::copy(list.begin(), list.end(), std::back_inserter(vec.at(index));
}
Run Code Online (Sandbox Code Playgroud)
好的。这样插入就完成了。值得注意的是:
向量的大小为:613284686向量中的条目为:3638243731 //通过遍历向量索引并在每个索引处添加std :: lists的大小来计算得出。
现在,由于有3638243731个指针条目,因此我希望此向量占用的内存约为30Gb。3638243731 * 8(字节)=〜30Gb
但是但是当我将这些数据存储在内存中时,内存峰值将达到400G。
然后我用以下方法清除此向量:
std::vector<std::list<nl_net> >& ccInfo = getVec(); // getVec defined somewhere and return me original vec.
std::vector<std::list<nl_net> >::iterator it = ccInfo.begin();
for(; it != ccInfo.end(); ++it) {
(*it).clear();
}
ccInfo.clear(); // Since it is an reference
std::vector<std::list<nl_net> >().swap(ccInfo); // This makes the capacity of the vector 0.
Run Code Online (Sandbox Code Playgroud)
好了,清除此向量后,内存下降到100G。从向量来看,这实在太多了。
你们都想纠正我在这里我没有理解的内容吗?
PS我无法在较小的情况下复制它,并且它正在我的项目中。
Run Code Online (Sandbox Code Playgroud)vec.resize(613284686);此时,向量的容量和大小将为613284686
这将是至少 613284686.这可能是更多的。
Run Code Online (Sandbox Code Playgroud)std::vector<std::list<nl_net> >().swap(ccInfo); // This makes the capacity of the vector 0.
从技术上讲,标准并不能保证默认构造的向量的容量不会为0 ...但是实际上,这可能是正确的。
现在,由于有3638243731个指针条目,因此我希望此向量占用的内存约为30Gb。3638243731 * 8(字节)
但是向量不包含指针。它包含std::list<ABC*>对象。因此,您应该期望vec.capacity() * sizeof(std::list<ABC*>)向量缓冲区本身使用的字节。每个列表至少都有一个指向开始和结束的指针。
此外,您应该期望每个列表中的每个元素也要使用内存。由于列表是双向链接的,因此您应该期望大约两个指针加上每个元素的内存值(第三个指针)。
同样,列表中的每个指针显然都指向一个ABC对象,并且每个指针也使用sizeof(ABC)内存。
此外,由于链接列表的每个元素都是单独分配的,并且每个动态分配都需要记账,因此可以单独取消分配它们,并且每个分配都必须与最大本机对齐方式对齐,并且免费存储可能会分散在执行过程中,每个动态分配都会有很多开销。
好了,清除此向量后,内存下降到100G。
对于语言实现来说,保留从操作系统分配的(某些)内存是非常典型的。如果目标系统记录了明确要求释放此类内存的实现特定功能,则可以尝试使用该功能。
但是,如果向量缓冲区不是最新的动态分配,则其释放可能会在免费存储区中留下大量可重复使用的区域,但是如果存在稍后的分配,则所有的内存可能无法释放回操作系统。
即使语言实现将内存释放给了OS,OS还是很典型的做法是为进程保留内存映射,直到另一个进程实际上需要该内存用于其他用途。因此,根据您测量内存使用情况的方式,结果可能不一定有意义。
可能有用的一般经验法则:
| 归档时间: |
|
| 查看次数: |
120 次 |
| 最近记录: |