IT技术博客大学习 共学习 共进步

多进程资源共享及多样化加载

云风的 BLOG 2010-11-14 21:07:43 浏览 3,005 次

梦幻西游在去年出了个新版本,在这个版本中,采用了 3d 技术渲染人物。我参加过部分的技术讨论。总的来说,对于公司的关键产品,是以稳定性为第一。所以不希望对程序做大改动。最好以独立扩充的模块为主。所以最终采用的技术是用 3d 技术渲染成图片,再依靠旧的程序框架跑起来。

采用 3d 渲染,主要是为了解决人物换装时的图片资源组合爆炸问题。当然还有更绚的特效等。

最近,梦幻西游的项目经理提出,新的版本性能依旧有些问题。当老的版本可以同时打开 5 个客户端时,新的版本只能开两个。允许用户同时开多个客户端,对梦幻西游这款产品非常重要。我最近几天就开始着力解决这个优化问题。


目前的方案是用一个独立进程去渲染图片,然后通过共享内存的方式,把渲染结果提供给游戏客户端。这较好的解决了多个客户端的性能下降问题。 我认为,这也是继续延用 2d engine 做核心的优势。(当然更重要原因是,这个游戏的客户端程序不适合重新制作,否则重制版一旦出现严重问题,对公司影响太大)

我研究了一下现有方案。考虑了几天,把一些细节重新设计了一下。感觉可以压榨出一些性能改善的空间。

3d 渲染本身并不是大的瓶颈,不过渲染结果从显存拷贝出来会是个问题。我个人倾向于使用软件渲染引擎。Pixomatic 是个不错的选择。不过这是个独立模块,倒是无所谓什么时候做。目前已经在用的这一块工作良好,暂时是不用动的。

另一块是从 32bit 平坦位图数据(渲染结果)压缩为 8bit 的 RLE 格式数据,和以前的 2d engine 中的数据格式兼容。这部分目前的代码运行时间大约相当于渲染环节的 1/4 。虽然还有一定的优化空间,不过暂时也可以不动。注:这里的优化,主要是集中在调色盘的计算上,目前用的算法是可以改进的。

在旧的 Engine 中,RLE 压缩后的图片是以行为单位储存。而每行数据,是记录的指针。这点可以修改一下,改记为相对数据块首的偏移量。这样,压缩图片数据就是地址无关的。更适合做进程间共享。这一点,大约花几个小时就能修改过来,而且不需要更改压缩图片数据在磁盘中的格式。


重点可以优化的地方在:我们可以把所有图片加载的环节全部移到单一的进程中。而不仅仅只是用一个独立进程负责实时渲染。这可以降低在多个游戏进程同时工作时的 IO 压力。

其实,现代操作系统,已经会把所有闲置内存用于磁盘 cache 。所以,重复加载文件,只是一些内存拷贝工作。不过这个工作也正是消耗 CPU 时间的工作。减少重复加载的数据量,也可以减轻 CPU 负担。

让多个游戏进程共享资源,也可以减少总的内存开销。这就能极大的改善总体性能。


最终的方案,是用一个独立 128bit ID 来定义每个资源的请求。这个 128bit ID 是由整个请求的参数计算出来的。

游戏进程计算出 ID 后,每次需要资源前,都向资源提供进程提交 ID , 但并不等待回应。而资源进程,按优先次序,依次获取图片资源,并逐个广播地址给每个游戏进程。为了加快响应,可以先返回缺省替代图的地址,然后等资源获取完整后,再刷新一次完整的地址。

游戏进程则维护一张缓存表,每当资源进程通知它新的图片地址后,就更新表中的对应关系。

资源共享使用分页共享内存的方式。按经验数值,一页 8M 。每个游戏进程映射的共享区虚拟地址不一。但由于图片数据是地址无关的,所以不太所谓。整个共享空间可以达到 512M 足够游戏使用。

其实,这个资源管理程序,不限于从磁盘加载数据,或是利用 GPU 渲染图片。更可以从网络下载。只需要把共享推送机制最好就行了。需要解决的只是响应速度问题。

建议继续学习

  1. 图片动态局部毛玻璃模糊效果的实现 (阅读 14,702)
  2. 淘宝图片存储架构 (阅读 10,844)
  3. 解决IE6从Nginx服务器下载图片不Cache的Bug (阅读 8,221)
  4. Python 多进程日志记录 (阅读 7,685)
  5. 精于图片处理的10款jQuery插件 (阅读 7,261)
  6. When we`re only No.2, we try harder之聊天表情设计小探讨 (阅读 7,122)
  7. 通过php+imagick 创建PDF图片预览 (阅读 6,983)
  8. phpThumb:强大的缩微图类 (阅读 6,622)
  9. js实现预加载图片让图片快速显示 (阅读 6,122)
  10. 利用开源的Gearman框架构建分布式图片处理平台[原创] (阅读 5,224)