2009年3月14日星期六

改写了继承时代码复用的方式

原先在对象继承时,我采用的是复制一份代码,同时对引用对象变量、调用函数、获取字符串资源等操作进行了映射转换。

目前看来,因为复制可能会导致大量的重复内容(尤其是对CEGUI Window的映射基类代码很多),占用不少内存,对客户端来说这点很敏感。在前一段优化工作完成以后,我开始着手修改这方面的实现。

原先所有映射、合并的代码全部删除。新增继承时代码段的组织方式,并且增加处理函数绑定的功能(这点是driver处理较为奇特的一点,一个对象可以声明函数F的prototype,但是并不实现,此时调用代码如果被执行则会出错。如果将来派生对象实现了相应的函数F,则该对象对F函数的调用自动定位到F上)

同时,VM新增了一个“当前程序段组件"的概念,相当于C++在类调用基类时需要修改类的this指针(比如VC使用的的ECX)一样,如果调用函数,必须更新这个值。同时在访问对象变量、对象字符串资源时,需要根据这个值进行查找,这带来了一些性能上的损耗,不过相比之下,获得了内存上的节省更划算一些。(在服务器端,我更喜欢原先的方式,但是考虑兼顾两种实现数据结构实在太复杂了,只要放弃这点性能了)

ps. 昨天遇到一件很有意思的事情,我在调整代码时,编译出的汇编代码完全没有变化,只是switch-case跳转表偏移了8个字节,结果导致VM执行测试脚本的性能下降一半。具体原因我尚不详,可能和cache命中率有一定关系。当然,根据结果决定是否调整意义不大,因为随便修改一下其他地方的代码都可能会影响结果。这可能导致一个很奇特的情况:有时候你明明将代码优化的更好了,但是实测效果反而更差。如果你不理会这个测试结果,继续修改其他地方,某一天你就会发现你的优化发挥了作用... 相比之下,GCC编译出来的结果要稳定一些,不过这也可能和CPU不同有关系。

没有评论:

发表评论