stl的内存管理
stl提供各种各样的容器,大家都感受到了它给我们带来的方便,但是它也存在一定的问题。刚来百度的时候,查看编码规范的时候,看到一条建议不要使用stl,而使用百度自己的bsl,原因是stl的内存不可控,不太适合百度的线上服务。当时不了解这句话的真正含义,只是记住了,甚至在后来用的时候,发现其实bsl就是将stl改吧改吧,并没有觉得有什么好的,而且用起来还没有stl方便。只是在做新人题的时候,试着去用bsl中的东西,而没有用stl。
目前做的一个项目要加载一个一对多的关系。当时也没有细想,就想开一个map,键为一个unit64_t,值为一个set,set中存储uint。但是发现bsl中的map的值如果用了set这样的类型的话,编译是通不过的,最后我还是马虎了事,用了stl中的map和stl中的set。但是这个映射每小时会跟新一次,需要重新加载。我用了一个双buffer来解决这个问题,在程序一开始的时候,加载这个映射到0的位置,然后发现跟新,在加载到1的位置,等待一段时间后,再把0的位置的内存释放掉,下次重新加载的时候再放到1的位置,如此往复。程序写完后运行了一段时间,也没有什么问题。但是后来发现内存报警,原来这个程序很吃内存,原本不加这个映射5个g就能搞定,现在一加这个映射,峰值的时候会到20g。恰好那次正好适用的是一台16g内存的机器,所以没有办法,最后换了一台48g内存的机器,最后就没有什么问题了。
后来我观察发现,这个程序不是一开始就占20g的内存,而是在运行一段时间后,才出现这样的问题。后来想了想发现是stl的内存分配上的问题。在公司的wiki上查了查,发现一个叫pool_alloctor的东西可以解决内存分配的问题。其实这个pool_alloctor就是一个内存池的内存分配器。我把原有的内存分配器替换成pool_alloctor后还是不能解决问题,还是出现内存的报警。
后来,我想了想,发现其实我这个std::map<uint64_t, std::set<uint32_t> >是可以用std::multimap<uint64_t, uint32_t>代替。代替后有一个意向不到效果,以前很高的cpu占用降了下来,但是内存分配的问题还是没有解决。
最后还是在wiki继续找,发现那个pool_alloctor可以配合内存池使用。我想了想我的程序,其实就是频繁得申请和释放内存,而这个操作是在多个multimap上进行的。直觉告诉我,将这些multimap的内存分配由一个内存池来完成的话,就应该能解决这个问题,说干就干,代码修改后,我发现,困扰我的内存问题得到了解决。
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。