STL——string分析

来源:互联网 发布:期货模拟盘软件 编辑:程序博客网 时间:2024/05/22 03:42

STL——string分析

之前一直在实验室写数据库相关的开发,由于是开发一款内存数据库,所以对内存资源的适用显得尤为重要。在开发的时候由于想快速搭建原型,所以大量利用的STL,特别是string,但是在使用的时候发现string的额外内存开销比较大,于是这里简单对string进行测试,测试很简单,在等量的原始数据下将vector

一. 测试工具

之前一直在用valgrind做内存泄漏的检测,但是并没有注意到valgrind还有检查内存占用率的作用,valgrind具体说明文档可以参考官方网站,massif工具说明。

具体执行命令为:valgrind --tool=massif ./a.out,massif工具便会输出快照文件massif.out.1333,利用ms_print massif.out.1333便可以查看具体的测试结果。

二. 测试结果

测试源代码如下所示:
TestVectorString.cpp

#include <iostream>#include <string>#include <vector>#include <stdlib.h>#include <unistd.h>using namespace std;int main( int argc , char **argv ) {    int size = atoi( argv[1] );    vector<string> container;    container.resize( size );    for( int i = 0 ; i < size ; ++ i ) {        string word("aaaa");        container[i] = word;    }    for(;;) {    }    return 0;}

TestVectorCharPtr.cpp

#include <iostream>#include <string>#include <vector>#include <stdlib.h>#include <unistd.h>#include <stdio.h>using namespace std;int main( int argc , char **argv ) {    int size = atoi( argv[1] );    vector<char*> container;    container.resize( size );    for( int i = 0 ; i < size ; ++ i ) {        char *str_ptr = new char[5];        sprintf( str_ptr, "aaaa" );        container[i] = str_ptr;    }    for(;;){    }    return 0;}

输入的数据量大小是100 000 000也就是400多M的原始数据(10 0000 000 * 5 bytes +10 0000 000 * 8bytes(指针开销))。valgrind测试TestVectorString.cpp结果如下图所示:
测试数据

可以看到巅峰内存达到400MB+,额外的开销很大,这是为什么呢,原始数据量在内存里面的大小也就是130MB+左右,String的内存开销未免也太大,可以接下来看下内存占用的分布,如下表所示:
测试数据

表中暴露的数据由useful-heap和extra-heap组成,在valgrind官方文档中是这么描述的:
The number of useful heap bytes allocated at that point. This reflects the number of bytes asked for by the program.

The number of extra heap bytes allocated at that point. This reflects the number of bytes allocated in excess of what the program asked for. There are two sources of extra heap bytes.

useful heap代表程序真正请求分配的内存空间,而extra heap则是由glibc内存管理器(ptmalloc)进行额外的内存分配(这一块儿和内存分配机制有关),抛开额外分配的内存区域,string new出来的空间月370MB也是相当恐怖的,对比string,我们测试vector<char*>的内存开销如下图所示:
内存开销图
内存开销表格

可以看见useful-heap的大小约为130MB和预期的原始数据一致,但是extra-heap接近180MB,这点也相当恐怖,这一块儿的内存管理和glibc的内存分配机制有关,所以这一块儿的空间没办法控制,但是我们可以来分析一下useful-heap为什么string比普通的char*多了这么多。

三. string实现分析

string是继承自base_string模板,在stringfwd.h中有这么一个typedef定义:
typedef basic_string<char> string;
找到basic_string.h 其中有一个私有成员如下:

struct _Rep_base{     size_type       _M_length;     size_type       _M_capacity;                  _Atomic_word        _M_refcount;                                };  

这个标志string的长度,容量,原子引用计数。都是八字节,加上string还需要维护一个char*指针,这就一共32个字节在元数据信息上。所以在数据量比较大的情况下,这种内存浪费还是相当恐怖的。

1 0
原创粉丝点击