« 关于群服务的实现 | 返回首页 | Go 语言初步 »

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

梦幻西游在去年出了个新版本,在这个版本中,采用了 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 渲染图片。更可以从网络下载。只需要把共享推送机制最好就行了。需要解决的只是响应速度问题。

Comments

。。。。guangjinlaishiyigeyiwai

难怪梦幻这么卡 把资源加载内存当中理所当然比加载硬盘资源来的快,但是小内存的电脑一下子就被淘汰了,同时显卡的渲染需求也被提升,集成显卡也被淘汰

现在机器越来越好了,可游戏越来越慢了!
还记得08年的时候,我一个人12开,一排号摆路上排个长队多威风,现在,三四开都感觉到有点吃力了!
说明下,我玩游戏时从不开其它其它软件或者看网页!

嗯哪!

进来掺和一脚

呵呵,很喜欢这种能将操作系统知识和实际程序紧密结合的专业博客,完全可以作为我们大学操作系统课程的课外读物研读。
我是个梦幻迷,初三开始玩,还带着我弟弟一起玩哎。这些年里,我几乎见证了梦幻所有的历史。一晃就要大学毕业了,时间过得可真快呀。。。
真希望有一天能进网易开发游戏,只是目前知识匮乏,还得努力。。。

云风,你应该向丁老总建议做个mac下的梦幻西游,我觉得会有一定的用户和市场

原来啊,我说网速那么慢都可玩游戏呢。

技术性很强的文章。有空去我博客围观。http://www.youngsunblog.com

真是有点看不太懂

@daseny

是产品加市场系,复杂的构成,所以对于用户体验比较重视。
因为留言的基本上都是技术高手,所以只能打打擦边球O(∩_∩)O
这次《梦幻西游》的推广是很成功的,技术支持很强。
没有好技术,很多玩法也就不能实现了。

有个小问题,《梦幻西游》不是今年7月才推的3D唯美版么?你说的3D渲染版本就是这个?还是以前的老版本就已经是3D渲染了……优化的方案能做到像以前那样5开了么?

http://tfdsy.com 托福替考

谢谢 daseny 同学的解释。

补充一下,上限的问题。一个是估算,二个是超过上限后,最终那些没有加载进来的图片会使用缺省图片。这跟来不及加载是一样的。对所有图片的管理是 FIFO 的。

我们的 2d engine 是直接对压缩图片进行绘制。也就是边解边输出到屏幕。所以共享压缩数据更能节省内存。

@feng
说是Flyweight模式也没错,但是我想boost应该是不能直接达成目标的,因为要跨越进程边界。

@cat000
参考下云风之前关于西游的文章,这个上限应该是量化估算的结果。

@夏歌
用独立进程加载图片,多开能节省内存,单开的话(比原有方式)增加的内存消耗应该也不大。当然CPU消耗和响应速度是要牺牲一点儿的 :)
这里云风设计了缺省资源(比如默认服装),这样用户角度应该能接受响应速度。
你是产品系么?喜欢你留言的态度。大家都以自己的角度交流看法,都受自己领域的限制,太自以为是会把自己钉在柱子上的。

@alamiye010
依然是领域的问题啊 :)
我觉得作为技术系牛人,云风的主要职责是解决这个问题,提出这个问题的可能是产品系的人。
你的话让我想起来过去站在“IE巨人”肩膀上大话西游,呵呵。

细节记不清楚了,不过使用独立加载进程的情况下,资源由加载进程解压为平坦位图,引擎直接使用平坦位图是否会更快一些?

D3D的托管资源和显存好像不能进程间共享吧?这样多开,内存和显存还是很浪费.不用托管资源开发起来又很麻烦.最好还是做成单进程多窗口渲染模式,这样也不需要单独的资源进程了.

D3D下,当资源占用过大时,再多开一个客户端,连创建设备都不会成功.

与其如此费时费力费人的去深究过去传统的游戏开发方式,何不把心思多花在设计游戏可玩性娱乐性上。像梦幻西游这样的游戏利用站在silverlight这样巨人的肩膀之上都不难实现吧。

太技术性的问题看不懂。说一说游戏本身,梦幻西游已经算得上国内的古董游戏了,新版本推出不仅仅需要维系旧有的用户,还需要适应更多新的用户。现在梦幻中除了年轻人外,还有很多长者。他们一般不会用太高配置的电脑,遇到电脑问题也大懂得去解决(btw,这部分用户也是360的忠实粉丝,因其简单好操作)。他们需要的是一款比较稳定,不太影响其他软件运行,不会给电脑带来负担的游戏。他们不一定需要多开,不过能够多开的游戏,内存占用少,或许也会更受到他们的喜欢。扯远了。

说到软件渲染,不妨试试我写的基于混合算法的软件渲染器

顺便放个Demo

http://cid-69cd46bd0bcfac39.office.live.com/self.aspx/.Public/Hybird3D.rar

膜拜云大大

@cat00
如果图片资源超过 2G 怎么办呢?

如果图片资源超过512m怎么办呢

进来掺和一脚

Flyweight 模式的典型应用场景啊,boost 提供了现成的解决方案

用Google Reader看到了更新.
群中的一些功能确实是可以用google reader来代替.

Post a comment

非这个主题相关的留言请到:留言本