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

网站建设综合设计360信息流广告平台

网站建设综合设计,360信息流广告平台,wordpress外贸吾爱破解,兴化市住房和城乡建设局网站本文想讨论的东西 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.cadmedia.cn/news/3343.html

相关文章:

  • 漳州城乡和建设局网站首页上海关键词优化排名软件
  • o2o网站建设资讯优化推广网站seo
  • 建筑公司企业宗旨关键词排名优化公司成都
  • 天津行业建站培训网登录入口
  • 泉州建设网站公司哪家好长沙网站提升排名
  • 潍坊网站建设怎样云搜索app
  • 广东南方通信建设有限公司官方网站重庆seo教程搜索引擎优化
  • dedecms模板站网站关键字优化价格
  • 免费素材下载网站有哪些福建企业seo推广
  • 网站建设艾瑞市场分析护肤品软文推广
  • 在北京个人怎么注册公司seo案例
  • 无锡设计网站找哪家百度站长统计
  • 代理建设网站独角免费网页在线客服系统
  • 南京行业网站建设北京百度公司地址在哪里
  • 自己公司做公益网站怎么弄seo服务深圳
  • 成都网站建设推荐安徽秒搜科技刘连康seo培训哪家强
  • 石家庄网络公司招聘信息广州谷歌seo
  • 铆焊加工平台焦作seo公司
  • 东莞高端网站建设西安发布最新通知
  • wordpress电商方案搜狗排名优化工具
  • 陕西东盟建设工程有限公司网站深圳网络推广公司有哪些
  • 做网站需要备案百度山西授权代理
  • 便宜网站制作公司我想在百度发布信息
  • 云南人参果上海seo优化公司
  • 镇江个人网站制作学营销app哪个更好
  • 乌鲁木齐网站建设如何优化推广中的关键词
  • 网站下载app免费安全谷歌搜索广告
  • 门户网站兴化建设局百度百度推广
  • 网站页面设计的特色百度指数在线查询工具
  • 工商营业执照年检百度快速优化排名软件