信息化 频道

企业信息化成功 要素及风险状况分析


【IT168 专稿】

    下面是示例程序使用及未使用这个未公开MFC类的对比情况截图,是不是有点心动了呢,接着往下看。



简介

    如果你经常浏览MFC的源代码,说不定就会有意想不到的惊喜发现,这不,很快就发现了一个,它是一个小工具类的集合,允许为特定类的对象定义怎样为其动态分配内存,这个类就是CFixecAlloc,通常它在大家熟悉的CString类的内部,用来分配字符串缓冲区。而我们今天要说的,就是如何在现有代码中,应用CFixecAlloc类,只花最少的修改成本来获取可观的性能提升,本文中探讨CRT动态分配的开销、针对CRT不足之处的备选方法、对CFixecAlloc类的剖析、及如何在程序中使用CFixecAlloc,最后,将在一个示例程序中证明这一切。

为什么不用malloc/free、new/delete呢?

   众所周知,动态内存分配开销非常大,它会导致程序执行时间上的性能损耗,而且占用空间也更大,如果还不相信,可以亲自查看一下CRT源代码中提供的malloc.c文件,怎么说呢,malloc()函数有点复杂,执行起来可能要花点时间;至于空间上的开销,说起来就稍有点繁琐了,基本上编译程序时不同版本的VC++、程序运行时不同版本的Windows,都会用到不同版本的堆,但这已超出了本文的范围。如果真的对CRT如何选择堆的版本很感兴趣,可以看一下heapinit.c文件中的__heap_select()函数。在CRT的winheap.h头文件中,定义了三种不同版本堆:

    __SYSTEM_HEAP
    __V5_HEAP
    __V6_HEAP

    V5及V6版本映射的堆实现,对CRT库来说是私有的,而系统堆(system heap)直接映射到Win32堆服务(如HeapCreate()、HeapAlloc()等等)。对于V5及V6版本,查看CRT源代码之后就可完全知道其空间开销,例如,对V6堆而言,就可找到下面这行语句:

//添加8个字节的开销并求整到下一个参数大小 
sizeEntry = (intSize + 2 * (int)sizeof(int) +
(BYTES_PER_PARA - 1)) & ~(BYTES_PER_PARA - 1);
    BYTES_PER_PARA等同于16字节,这是一个非常大的开销,如果我们只需要12字节呢,而CRT将会为此保留32字节,这已经比所需的两倍还多了。但V5及V6堆现今已很少使用了,且也没有源代码,所以还不能确切了解HeapAlloc()的开销是多少,然而,存在一定程度上的开销总是不争的事实,微软对此在HeapCreate()文档中的声明是:

    系统使用私有堆中的内存,用于存储支撑堆的结构,因此,并不是所有规定的堆大小对进程来说都是可用的。例如,如果HeapAlloc()函数从一个最大64K的堆中请求64k(千字节)内存,那么会因为存在系统开销而调用失败。

0
相关文章