本来今天就可以提交了,但是我昨天晚上想了一下,仍然有些立竿见影的事情可以做。
目前driver使用了38M内存,但是占用空间达50M,这是管理开销引起的。系统在启动的时候,需要加载大量的脚本bytecode,加载的过程中申请了很多小片内存,但是显然这些内存在整个生命周期内都不会被释放。所以,我引入了稳定堆的做法,准备一块平坦的内存,这些小片内存都优先在这个堆上申请,它们不会被释放,从而达到节约管理开销。
为了做到这一步,我首先整理了一下driver在编译、加载bytecode阶段的代码。将稳定的内存和临时使用的内存分开,这花费了我一个上午的时间。下午又花了点时间顺便优化了加载bytecode的过程,给它加了一个缓冲 - 本来我认为没有必要,因为driver是将整个bytecode文件读入内存然后分析的,但是考虑直接从driver封装的io读取内存数据额外CPU开销还是有点大,所以仍然做了一个本地的小型缓冲,4K。效果还不错,启动速度提高了15%左右。
将申请分开以后,我就开始着手添加稳定堆。这个实现非常简单,就是事先准备好一段内存,当申请的时候简单的将指针累加返回即可。申请的速度非常快,而且额外开销只有0-3字节,这是为了确保对齐。实现本身很简单,不过我还需要增加相应的profile功能 - 事实上,只实现功能只能算做了一半的工作,没有足够的profile方法很难进行维护、优化和各种各种诊断。
采用稳定堆的做法并没有减少任何直接的内存使用,但是管理开销减少了3M多,和我预期的差不多。最终客户端启动只占119M,想想一个月前客户端启动就是210M内存,还算是欣慰。driver占用的内存从130M下降到了43M,节约了90M左右。
晚上开始提交相应的库,这个版本我将尽快更新到外网,以便发现稳定性方面的问题。也不知道该说运气好还是不好,刚刚提交我就发现了一个问题,花了点时间解决。
总的来说,今天的优化工作只是锦上添花,实际意义不大。因为目前已经到到了设计目标,从工程角度来说,并非要做到最节省才好。只是出于个人爱好,我又多花费了一天的时间。
最后:从实现逻辑的角度来说,脚本代码并不比C代码更浪费内存,甚至可以说会节省一些。在STL被广泛使用的今天,C语言的代码急剧增加。脚本代码在处理逻辑的时候,因为指令功能较强,实际上表达相同的逻辑,使用的指令并不会比汇编指令多。当然,使用脚本占用内存的真正问题在于变量上,由于需要携带类型,所以在大量处理整数时,脚本浪费的较多。
没有评论:
发表评论