当前位置: 首页 > wzjs >正文

吉林省建设信息网官网入吉毕节地seo

吉林省建设信息网官网入吉,毕节地seo,济南最好的网站制作公司,线上兼职本文想讨论的东西 vector作为一种常见的容器,我们在日常的C开发中,非常的常见,但是对于vector的使用过程中的内存分配情况,包括虚拟内存和物理内存的分配,感觉不是特别的清晰,作者也是想写一个demo&#x…

本文想讨论的东西

vector作为一种常见的容器,我们在日常的C++开发中,非常的常见,但是对于vector的使用过程中的内存分配情况,包括虚拟内存和物理内存的分配,感觉不是特别的清晰,作者也是想写一个demo,和大家一起来学习,详细分析vector在使用过程中的内存分配情况。

一些需要掌握的铺垫知识

vector 中的size,capacity, shrink_to_fit方法

size是反应vector中现在的元素个数
capacity是最多能存放多少个元素,如果超过这个capacity就会扩容,所以为了避免频繁的扩容,而带来的拷贝开销,我们会
使用reserve方法
shrink_to_fit 是收缩内存到我们的size的大小,也就是会减少capacity到size大小,也就是会回收物理内存

关于linux系统中的查看内存的指令

我们通常使用 pmap -X pid 指令来把某个进程的虚拟内存使用和rss(实际使用物理内存进行展示)

关于brk和mmap

这里只是简单的介绍下,glibc的这个库里有两个调用常用来进行分配和释放虚拟内存,malloc和free,malloc会进行调用brk或者是mmap来分配内存,而free会通过调用 brk和munmap来释放虚拟内存内存。
一般情况下 小内存,小于128k的时候,会brk,
大内存,大于128k的时候用 mmap.
而在malloc以后,不会马上的分配物理内存,而是当第一次使用虚拟的内存的时候,触发内核的page fault来分配物理内存。

而在free以后,如果是调用了munmap会立即的回收物理内存
而如果调用的是brk, 系统可能不会马上回收物理内存。

关于new,delete, malloc,free

这里其它区别我不再赘述,只是想说一点,是否会触发分配物理内存的情况
new:会有两步操作,第一步是 调用malloc分配虚拟内存,第二步是调用对应的构造函数,如果构造函数中有对成员变量的赋值操作,也就是有对其的内存进行实际的使用,就会触发内核的缺页中断,进行物理内存分配。
delete:会有两步操作,第一步是 调用对应的析构函数,然后第二步是调用 free. 然后至于free操作,会不会释放物理内存就要看调用的是brk还是munmap了。

关于strace指令

strace 就是systemcall trace也就是系统调用跟踪,也就是当我们进行系统调用的时候,会被这个指令跟踪下来,我们这里涉及到的系统调用主要是,brk,mmap,munmap.

关于pod类型

本文刚开始会讨论vector里存储pod类型,然后再接下来讨论vector里存储非pod类型,所以我们要介绍下什么是pod类型
所谓pod类型就是 (Plain Old Data,即“普通旧数据类型”)是一种特殊的类型分类,它表示简单的、与 C 语言兼容的数据结构。
它有两个特点:
1.平凡可复制
所以的平凡可复制就是,对象的内存布局是连续的,可以直接用 memcpy 安全地复制
满足以下条件:
默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数是 ​自动生成的​(或显式标记为 = default)。
没有虚函数或虚基类。
2.标准布局(Standard Layout)​
内存布局与 C 语言兼容,可以直接与其他语言(如 C)交互。
满足以下条件:
所有非静态成员变量具有相同的访问权限(如全部 public)。
没有基类(或所有基类都是空类且第一个成员是非静态成员)。
没有引用类型的成员。
类中最多有一个类有非静态成员变量。

代码例子(POD)

#include <cstddef>
#include <iostream>
#include <unistd.h>
#include <vector>void pause(const char* msg){std::cout << "Pause " << msg << " pid of this process " << getpid() <<std::endl;std::cout << "Run pmap -X " << getpid() << std::endl;std::cin.get(); // press enter to continue.
}int main() {std::vector<int> test_vector;std::cout<<"before reserve size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("before reserve 100 000 000");//stage 1 virtual memorytest_vector.reserve(100000000);std::cout<<"after reserve size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after reserve 100 000 000");//state 2 use virtual memory for physical memory usefor(size_t i=0; i<100000000; i++){test_vector.push_back(12);}std::cout<<"after writing data size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after writing data");//state 3 clear vectortest_vector.clear();std::cout<<"after clear size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after clear vector");//state 4 shrink to fittest_vector.shrink_to_fit();std::cout<<"after shrink_to_fit size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after shrink_to_fit");return 0;
}

我们设计了一个代码,自定义了一个pause函数,这个函数,会暂停进程,并且给出提示信息,执行pmap 命令,然后我们可以看到不同的阶段,对应的console控制台打印,以及pmap的输出。
程序编译指令:
g++ -static -std=c++11 -O0 test1.cpp -o test1
程序执行指令,用 strace进行跟踪系统调用情况:
strace -e brk,mmap,munmap ./test1

下面我么具体讲解每一个步骤,并且给出程序的输入截图:

1.reserve之前

before reserve
在这里插入图片描述

2.after reserve

在这里插入图片描述
在这里插入图片描述

3.after writing data

在这里插入图片描述
在这里插入图片描述

4.after clear size

在这里插入图片描述
在这里插入图片描述

5.after shrink_to_fit

在这里插入图片描述
在这里插入图片描述

代码例子(非POD)

#include <cstddef>
#include <iostream>
#include <unistd.h>
#include <vector>
#include <malloc.h>class TestClass{public:TestClass(){//std::cout<<"construct enter"<<std::endl;}~TestClass(){// std::cout<<"desconstruct enter"<<std::endl;}private:int a =10;int b=100;std::string c = "1234141324dgfdsgdffdakdfjkaljfkla";
};void pause(const char* msg){malloc_trim(0);std::cout << "Pause " << msg << " pid of this process " << getpid() <<std::endl;std::cout << "Run pmap -X " << getpid() << std::endl;std::cin.get(); // press enter to continue.
}int main() {std::vector<TestClass> test_vector;std::cout<< "size of std::string:"<< sizeof(std::string) << std::endl;std::cout<< "size of TestClass:"<< sizeof(TestClass) << std::endl;std::cout<<"before reserve size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("before reserve 100 000 000");//stage 1 virtual memorytest_vector.reserve(100000000);std::cout<<"after reserve size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after reserve 100 000 000");//state 2 use virtual memory for physical memory usefor(size_t i=0; i<100000000; i++){test_vector.push_back(std::move(TestClass()));}std::cout<<"after writing data size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after writing data");//state 3 clear vectortest_vector.clear();std::cout<<"after clear size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after clear vector");// //state 4 after clear, continue push back data// for(size_t i=0; i<100000000; i++){//     test_vector.push_back(std::move(TestClass()));// }// std::cout<<"after second writing data size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;// pause("second time after writing data");//state 5  shrink to fittest_vector.shrink_to_fit();std::cout<<"after shrink_to_fit size:"<< test_vector.size() << "capacity:" << test_vector.capacity()<<std::endl;pause("after shrink_to_fit");return 0;
}

编译代码:g++ -static -std=c++11 -O0 test1.cpp -o test1
执行代码:strace -e brk,mmap,munmap ./test1

1.before reserve

在这里插入图片描述
在这里插入图片描述

2.after reserve

在reserve的时候,因为数组的大小比较大,所以会触发用mmap分配到匿名区域,一会用pmap指令可以看到
这里要区分堆区域,小内存会被用brk分配到堆区域
在这里插入图片描述
在这里插入图片描述

3.after writing data

这里和平凡的相比,不单增加了物理内存,也会增加虚拟内存
在这里插入图片描述
在这里插入图片描述

4.after clear

clear以后,由于我们的类里有std::string,会触发析构函数的执行,string的析构函数里,会释放掉堆上的内存,所以这个时候,clear会减少堆上的内存,这个是和平凡类型不一样的地方。
同时也需要注意,这个非POD的内存也不一定会马上被释放,如果其他进程不用的话,可能还会继续保留,之所以我这里马上释放,是因为我在代码里加了强制回收物理内存。
void pause(const char* msg){
malloc_trim(0);
std::cout << "Pause " << msg << " pid of this process " << getpid() <<std::endl;
std::cout << "Run pmap -X " << getpid() << std::endl;
std::cin.get(); // press enter to continue.
}

在这里插入图片描述
在这里插入图片描述

5.after shrink_to_fit

在这里插入图片描述
在这里插入图片描述

总结

本文讨论的初衷是想了解vector 的整个声明过程中对于内存的使用情况,特别是物理内存,便于我们对程序代码进行优化,这里主要有两种优化。

1.优化内存使用

如果我们的代码是在内存资源比较紧张的环境,则需要再使用完vector后,进行及时的shrink_to_fit清理内存,这个时候就会导致再次使用的时候又需要重新申请虚拟内存,以及要使用的时候触发page fault来进行分配物理内存,这个就会比较耗时。

2.减少程序的执行时间

这个在我们资源比较充足的情况下,我们可以拿空间换时间,只是调用clear,然后后续使用vector 的时候,直接使用原有的内存就可以了,不必要每次都清理掉物理内存

3.非POD的情况特殊

因为非POD可能会导致clear的时候会释放物理内存,所以用clear可能就不太行了,就需要自己实现内存池

http://www.dtcms.com/wzjs/18013.html

相关文章:

  • 装修网十大平台网站seo是干什么的
  • 成都专业做婚恋网站的网络科技公司域名买卖交易平台
  • 三合一网站建设方案seo职位
  • 网站做推广有用吗seo关键字排名
  • 网页制作基础教程试卷网站搜索排优化怎么做
  • 天津葛沽 网站建设公司注册平台
  • 厚街找人做网站网络营销成功案例有哪些
  • 事业单位可以建设网站吗成都网站快速开发
  • 大连免费建站模板网店怎么推广和宣传
  • 平顶山做网站公司目前最新的营销方式有哪些
  • 北戴河区建设局网站网站建设高端公司
  • 网站名称及网址seo教程技术资源
  • 什么网站能找到做展览的工人太原seo顾问
  • 域名空间做网站推广营销策划方案
  • 求个网站2022网络营销的六个特点
  • 贵阳有哪家做网站建设好点的谷歌chrome浏览器官方下载
  • 信丰做网站aso优化的主要内容
  • 网站主机选择与优化百度中心
  • 怎么做网站里面的模块百度一下首页设为主页
  • 网站备案流程核验单济南百度快照推广公司
  • 网站架设软件可以直接打开网站的网页
  • 360网站怎么做免费聊天软件
  • 网站开发应如何入账优化设计高中
  • wordpress 图片id郴州网站seo外包
  • 网站备案真实性检验单竞价托管是啥意思
  • 做谷歌网站使用什么统计代码seo网络优化培训
  • 独立网站建设教程视频seo网站推广软件
  • 6免费建站的网站青岛网站制作设计
  • 射阳住房和建设局网站直播发布会
  • 网站建设收获与体会2345网址导航是什么浏览器