以前我在写手游的时候仅知道尽量避免使用String类型来绘制字符串,因为会造成游戏效率降低,GC无法回收的问题。但是具体的细节却不知道,最近在研究C语言的时候才发现为什么String会造成这些麻烦的具体原因。
首先我老调重谈,写下C语言中 stack(栈) 和 heap(堆)的问题:
stack在内存中是一块连续的内存块, 可自动分配释放 ,一般用来存放函数的参数值,局部变量的值等(如int a,b 就是自动开辟栈空间)。大家在for循环中可能出现的overflow错误,很多都是由于寻找的值超过stack的最大内存范围引起的,stack的内存大小被控制在1M~2M内,手机上更小。
heap在内存中是不连续的内存块,由程序员自己分配,常用的就是malloc(对应于JAVA/C++中的new)。这个heap是比较灵活的,但是由于他的内存的不连续性,很容易造成产生内存碎片,而且分配的效率比较低下。而String 是个char[],这个东西只有分配在heap上。 而访问heap主要是通过指针间接访问(需要经过3步间接访问,而stack上的最多只需要2步), 在汇编层面上看,是要比存放在stack中的数据多至少1条的汇编指令。如果String越长(1块内存块存放长度255,超过以后会再申请新的内存块。),Heap中的内存块就越不连续,需要指针跳转的就越多,这就造成了效率降低。在手机游戏不停绘制界面的时候,如果不停drawString效率可想而知。
经过我研究了一下,发现String的以下特性,有点类似C++ STL容器里的<String>:
String这个玩意在删除时候, 一般不会释放它已经分配的内存,为的是下次使用时可以更高效.
String这个玩意在追加少量字符时候,效率一般不会有很大的变化。
String这个玩意在替换,删除字符时候,会进行内存复制,效率降低,而且很容易产生内存碎片。JAVA的GC无法回收,不信你可以在NOKIA机子上写个程序,不停的删添String,再GC,一段时间后,就算关闭程序,打开其他程序时候依然会报内存不足,而且操作系统运行速度明显降低。
呵呵欢迎没事到我的手机开发资料站坐坐:www.j2megame.com.