dbd到mongo的序列化问题及稳定性

最近工作压力有点大,情绪偶然会失控,要好好反省一下自己。

 

上周本来打算写CSP相关的东西,但是目前做得还不够多,积累的经验不足,就放弃了。中间找到很好的参考资料,一并放在这里。一篇是比较短的论文,可以观其大略:http://www.cs.ucf.edu/courses/cop4020/sum2009/CSP-hoare.pdf,另一个链接是hoare写的关于进程演算的书:https://dl.dropboxusercontent.com/u/5660734/CSPbook_2004_Hoare.rar 对于理解CSP这个模型的数学基础很有帮助。不过书好长,还没看完。。。

 

本周合并了另一个项目组对mongodb改造的修改,对方完全重写我的代码,但没有配套单元测试,合并当天就测出bug了,有点碎碎念啊。没办法,硬着头皮剥离一部分依赖,独立出一个可执行文件来测bson_format的问题。正如之前写的这篇博客提到的,难点在于类型系统的对接。本次修改增加了一个array迭代,保证初次在引擎这边分配array的时候,已经是一块足够长的内存,而不是我原来实现时,迭代bson,有一个元素就合并一个。另外,上次序列化为bson时,我错将array当mapping来序列化了,原有的测试只针对长度,没针对具体内容,本次修改已经修正。

 

另外一个地方,是关于内存对象的生命周期的。本次修改直接重写了dbo_new, dbo_load, dbo_unload等方法,这些方法控制了dbd内存中,存放在apr_list里的一系列db对象。gamed通过rpc调用,以dbo_new或者dbo_load方法创建对象后,除非调用dbo_unload,否则对象是不会被释放的,整个生命周期非常清晰。虽然dbd启动过程中初始化了vm虚拟机,实际上并没有跑lpc脚本,所有工作都是在c层实现的。本次修改中,在序列化过程里,用到的字符串局部变量,都是通过vm虚拟机来申请和释放的。个人对此持保留看法。在序列化过程中,所用到的key值都是临时性的,bson化后就没有意义。一个简单粗暴的做法,就是直接在函数内定义定长字符串数组,然后每次需要序列化bson key的时候,都复制/格式化到这个数组上。这一方面可以避免堆区内存分配,另一方面避免无谓的内存泄露,以及可能出现的二次释放问题。

 

稍后,通过单元测试,修正了当天测试暴露出来的,反序列化array嵌套mapping对象时,array元素没有初始化好,导致序列化嵌套mapping时,引擎core dump的问题。接着,对方又抛出了一个新的修改,依然是没有单元测试。。目标是修正引擎的概率性崩溃,依据是序列化mapping过程中,对key做字符串化操作时,会改动到原有的mapping,然后造成内存泄露和/或mapping元素的二次释放问题,引致引擎崩溃。经单元测试发现,这个理由不成立,但代码里的确会有误释放的问题。至于误释放为什么没有引起单元测试崩溃,这个还需要看看gc那一块的代码。这次bug fix就没有吸合了,稍后通过在函数内定义一个局部定长字符串数组,加上key的复制来解决吧。

 

通过这几次引擎的修改,越来越发现,没有单元测试的代码,真的会没有信心的。不是说你用这个代码跑了两周,没有发现存储有问题,这个代码就是没有问题的。不同项目组里,用到的储存结构不一样,也许你的代码嵌套3层以后就会崩掉呢?或者就是这次暴露出的,复合类型的嵌套储存bug呢?没有办法用单元测试重现的bug,只靠看代码猜测,我觉得是不靠谱的,因为修好后你也没办法重现bug的环境,看看本次修改是否有效。希望大伙能够早日认同这个道理

 

做完底层又要赶逻辑代码,差点回不了家,残念……

posted on 2013-10-14 00:08  lifehacker  阅读(921)  评论(0编辑  收藏  举报

导航