c++ 哪些 容器 手机内存64和128选哪个 连续

曾经写过一个文本比较的程序其功能是先扫描两个服务器中指定的目录,按照给定的时间参数把符合条件的文件路径写入列表中然后比较这两个服务器中分别生成的列表文件做文件备份。一开始没有考虑到文件数量会很庞大所以按照以前的编程习惯使用两个常用的vector容器来存放两个列表中的内容,然後做比较

 

如果上面的程序用于文件数量在几百之内的目录中,你可能不会发现性能有什么问题但想象一下,如果你现在处理的是一个網站的图片服务器里面存放的图片数量是几十万张,同时每张图片还有2~3张对应的缩略图这样子我们在做比较时按照上面的算法来处悝的话就是n*n的时间复杂度(其中n是百万级别的)……我曾试着跑这个程序,结果运行了5个小时还没得出结果就把它中止了

解决这个问题嘚思路很简单——抛弃你对容器的使用偏好,弄清楚需求后重新选择一个适合的容器因为在比较时我需要遍历容器进行查找,所以set是一個不错的选择:一是它二叉搜索树结构对元素进行存取二是插入新元素时它可以保证不会重复。代码中修改的地方不多但性能却有了驚人的改进:

 

同样的需求,使用vector时运行不止5个小时的时间使用set后的运行时间只有35秒,5小时和35秒啊!所以这一次我得到的经验教训就是:鈈要盲目地使用容器要弄清楚各个容器的内部算法是什么,然后根据实际情况选择合适的


变长一维数组连续存放的手机內存64和128选哪个块,有保留手机内存64和128选哪个堆中分配手机内存64和128选哪个;

支持[]操作,高效率的随机访问;

在最后增加元素时一般不需偠分配手机内存64和128选哪个空间,速度快;在中间或开始操作元素时要进行手机内存64和128选哪个拷贝效率低;

vector高效的原因在于配置了比其所容納的元素更多的手机内存64和128选哪个手机内存64和128选哪个重新配置会花很多时间;

注:需要高效的随即存取,而不在乎插入和删除使用vector

双姠链表,手机内存64和128选哪个空间上可能是不连续的无保留手机内存64和128选哪个,堆中分配手机内存64和128选哪个;

不支持随机存取开始和结尾元素的访问时间快,其它元素都O(n)

在任何位置安插和删除元素速度都比较快,安插和删除操作不会使其他元素的各个pointerreference,iterator失效;

注:夶量的插入和删除而不关系随即存取使用list。

双端队列在堆上分配手机内存64和128选哪个,一个堆保存几个元素而堆之间使用指针连接;

支持[]操作,在首端和末端插入和删除元素比较快在中部插入和删除则比较慢,像是listvector的结合;

注:关心插入和删除并关心随即存取折中使用deque

有序集合,使用平衡二叉树存储按照给定的排序规则(默认按less排序)对set中的数据进行排序;

set中不允许有重复元素,multiset中运行有重复え素;

两者不支持直接存取元素的操作;

因为是自动排序查找元素速度比较快;
不能直接改变元素值,否则会打乱原本正确的顺序必須先下删除旧元素,再插入新的元素

字典库,一个值映射成另一个值使用平衡二叉树存储,按照给定的排序规则对map中的key值进行排序;

根据已知的key值查找元素比较快;

插入和删除操作比较慢

本文用于探讨在共享手机内存64和128選哪个中使用容器的好处以及几种在共享手机内存64和128选哪个中C++模板容器的方法。

1 为什么要在共享手机内存64和128选哪个中使用模板容器

为什么要避开普通手机内存64和128选哪个而选择共享手机内存64和128选哪个,那肯定是使用共享手机内存64和128选哪个的优势:

  • 共享手机内存64和128选哪个可鉯在多进程间共享到达进程间通信的方式。
  • 共享手机内存64和128选哪个可以在进程的生命周期以外仍然存在这就可以保证在短暂停止服务(服务进程coredump,更新变更)后服务进程仍然可以继续使用这些共享手机内存64和128选哪个的数据。

如果这些优势在加上C++容器模板使用方便开發快速的优势,无疑是双剑合璧成为服务器开发的利刃。

2 在共享手机内存64和128选哪个中使用模板容器最大难点是

但如果要要做到让容器茬模板中使用,最大的麻烦是什么就是指针。(同步当然也是一个问题但我这儿强调的是容器的移植)

当然一般而言,这个指针的地址一般还是指向共享手机内存64和128选哪个的内部数据为什么不会出现指向各自私有数据的情况?如果2个进程A,共享的数据里面的一个指针茬进程A表示进程A的私有地址,在进程B里面标识B的私有地址这明显是你逻辑设计有问题。

而内部指针对于我们上面提到的2个优点其都是忝敌。另外也要注意如果数据需要多进程共享,你的数据也必须是POD的数据如果有虚表指针,那么也不可能实现共享

多进程之间的共鼡的共享手机内存64和128选哪个,地址很可能是不一样的当然共享手机内存64和128选哪个的API上一般都可以建议固定起始地址,但既然是建议那僦可能不遵守,而且这需要你熟悉进程的地址空间分布而且对于开发者和运维者,一旦使用的共享手机内存64和128选哪个多了使用固定地址绝对是噩梦。

而对于服务器上一次映射的地址,有可能和重启后的映射地址不一致

//mmap函数的第一个参数,就是建议地址
 

而对于解决指針这种问题最好的方法(或者说唯一的方法)就是不记录指针而记录相对的偏移地址,所有的计算都根据偏移地址处理

目前探讨在共享手机内存64和128选哪个中使用模板的方法,我见到过的思路和实现大致3种一种是定制STL的容器手机内存64和128选哪个分配器,一种是ACE提供的使用哋址无关的分配方法一种是BOOST的interprocess的实现,我们分开聊聊这些方法的优点和缺点

3 定制STL的分配器

如果早年(04年以前)在网上的论坛搜索答案,大部分给的答案是这个表面看这也是一个比较好和简单的答案,最大程度的利用STL容器现有的代码

但其实这个答案并不一定靠谱。写┅个共享手机内存64和128选哪个的分配器肯定不是什么难事难在如果我们要把容器放入共享手机内存64和128选哪个的那几个目的,使用STL的容器的實现为什么呢,还是因为指针

首先,很多STL容器实现里面是有大量指针的比如list的环形队列的prev指针和next指针,map底层红黑树实现的3个指针這些在容器内部都是用真正的手机内存64和128选哪个地址表示的。

所以说这个答案完全要看你的STL的内部实现是否有指针如果有,那基本不可荇(当然你把数据放入共享手机内存64和128选哪个是可以的但你无法共享和重用)。比如SGI的实现和STLport的实现

4 ACE的与位置无关的分配

*()函数达到几乎和指针一样的行为(实际会调用addr(),得到真正的地址)ACE的实现有点意思,我们也费点力气剖析一下

如果上图的例子,进程AB共享一段囲享手机内存64和128选哪个,分别映射在不同的地址上共享手机内存64和128选哪个中有一个结构S,S中要记录一个这段共享手机内存64和128选哪个中的叧外一个地址char *结构S可以使用ACE的ACE_Based_Pointer_Basic<char> 记录这个地址,ACE_Based_Pointer_Basic<char>分别使用2个长度记录自己到共享手机内存64和128选哪个起始地址的长度以及需要记录的地址箌共享手机内存64和128选哪个的起始位置的地址。然后两个进程就都可以通过this指针和2个偏移长度,计算得到需要记录的地址

ACE的实现上,自巳的手机内存64和128选哪个分配器记录了分配的地址空间起始地址和长度ACE_Based_Pointer_Basic<T>在构造的时候会根据自己的地址判断自己需要计算的起始地址是什麼。而且在封装上考虑比较舒服但需要提醒的是,你需要记录的地址必须仍然是这块共享手机内存64和128选哪个上的否则……(不解释)。

而且要说明的是ACE的自有容器虽然也支持使用共享手机内存64和128选哪个的分配器但由于ACE容器的内部也有大量的指针,而不是记录相对地址所以ACE的容器其实也不能在共享手机内存64和128选哪个中。所以ACE的学术气息更加浓烈一点实用性并不高(ACE的容器本身也不好用)。所以可以說ACE踹开了那扇门,但并没有进入这个殿堂

这几年BOOST开始流行,BOOST的interprocess库中一个在共享手机内存64和128选哪个容器手机内存64和128选哪个分配器的实现但要注意其配合使用容器vector,list是BOOST自己的container容器。这个分配器并不能和现有大部分STL实现配合使用

可以说其实BOOST的实现和ACE的思路是类似的,方法也是分配一个块共享手机内存64和128选哪个为这块共享手机内存64和128选哪个生成一个容器手机内存64和128选哪个分配器,这个分配器为这个容器垺务使用共享手机内存64和128选哪个容器分配器后,容器内部所有的地址记录相对地址而不是绝对地址。

对比ACEBOOST实现的不同,一方面BOOST的共享手机内存64和128选哪个管理和容器手机内存64和128选哪个分配器的思路很清晰整体设计思路还是在STL的体系之下,ACE诞生的年代过早容器整体体系和STL完全不相容,另外一方面BOOST在相对地址的处理上也简单一点。他只记录offset_ptr对象的this地址到需要记录的地址之间的长度

另外,BOOST代码虽然条悝上和STL容器一致但BOOST的代码阅读难度至少double于STLPort,传统调试跟踪代码的方式单步跟踪虽然有效但是很多变量都无法查询到实际值,宏满天飞期待剖析BOOST代码的大神出现。

而且另外一个小问题是我们申请的共享手机内存64和128选哪个的大小都是有一个大小限度的,而STL容器往往有随需增长的特点而这个特点和共享手机内存64和128选哪个其实也有一些不调和性。

ACE的问题在这个问题上给出过一些学术解依靠信号,异常等方式给你机会自己扩展手机内存64和128选哪个,但估计也就限于学术探讨范围

BOOST在这个问题上更加明了,当手机内存64和128选哪个不够分配的时候抛出bad_alloc异常反而更加清晰一点。

7 另外一种解思考,固定最大长度的容器

BOOST的实现固然不错但也有几个并不那么完美的地方,而且当时可以參考的思路还没有这样多(我自己实现自己容器的时候是2005年,BOOST的interprocess的库在08年才出现)

第一放入N个T类型的数据的容器到底需要多大共享手機内存64和128选哪个?因为容器本身是有消耗而这点BOOST并没有接口告诉我。对于使用共享手机内存64和128选哪个的容器我们都知道我们需要使用嘚最大数量是多少。

第二如果最大的尺寸我们已经知道。那么其实我们对于所有的可以在一开始就分配好空间而不是在每次push_back的时候调鼡alloctor去分配地址,其实alloctor内部仍然使用了红黑树去管理所有的分配地址坦白说麻烦。而且由于最大尺寸固定我们所有的数据的内部位置关系都可以采用数组下标定位。这样也就一样省去了指针的麻烦

综合上面的考虑。我们当时的设计思路大致是根据你传入的参数判定告知调用者所需的手机内存64和128选哪个大小,调用者自己分配好手机内存64和128选哪个(可以是共享手机内存64和128选哪个)根据分配的手机内存64和128選哪个地址构造一个容器,容器的操作和模板基本一致也提供迭代器等方法等方法访问,容器的内部结构如下图

这个方法和STL容器的语法基本兼容,性能比BOOST的那个速度应该要快一点(不用在每次都alloc一个node节点)寸有所长,尺有所短这也算一个思路把。

具体的代码以后估計会开源

在共享手机内存64和128选哪个中使用模板容器的关键问题是指针的问题,相对地址是解决这???问题比较好的方法一个比较通鼡的方案是将所有的指针改成一个相对地址记录,还有一种思路对于容器的处理方式是将容器的所有数据按最大数量分配好使用下标处悝。

《STL源码剖析》 侯捷

《ACE程序员指南》 马维达

将C语言梳理一下分布在以下10个章节中:

  1. Linux-C成长之路(二):基本数据类型
  2. Linux-C成长之路(三):基本IO函数操作
  3. Linux-C成长之路(四):运算符
  4. Linux-C成长之路(五):控制流
  5. Linux-C成长之路(六):函数要义
  6. Linux-C成长之路(七):数组与指针
  7. Linux-C成长之路(八):存储类,动态手机内存64和128选哪个
  8. Linux-C成长之路(九):复合数据类型
  9. Linux-C成长之路(十):其他高级议题

本文永久更新链接地址

我要回帖

更多关于 手机内存64和128选哪个 的文章

 

随机推荐