最近三周按计划在做第一里程碑的发布工作,几乎所有新特性都冻结了。大家都在改 bug 和完善细节。
服务器的性能还有不小的问题,压力测试的结果不能满意。原本我希望可以轻松实现 40 人对 40 人的战场。现在看起来在目前台式机上还有困难,虽然换上高配置的服务器可以达到,但会增加不少成本。我们决定动手做一些优化。
固然过早优化的必要性不大,但早期发现的性能问题有可能是设计原因造成的。尽早发现设计中的错误,早点改正,比后期在低层次优化要省力的多。
我们采用的是大量进程(非 OS 进程,这里指 Erlang 进程)协作工作的模式。可以充分利用多核的优势,但却对内部通讯的数据交换产生的极大的压力。初步发现在多人对战时,90% 的内部通讯包是状态包的同步 。虽然我们的框架实现,会让单台机器上的 Erlang 进程间通讯,变成同一进程内的简单函数参数传递。但数据列集和内存复制还是会带来一些负荷。
目前还不太确定内部数据包传递的边际成本到底是否影响到整体性能,我打算从优化这一部分的设计和实现入手,确定问题所在。
状态同步,简单说就是一个玩家的 Agent 在做一个动作时,它需要把这个行为通知所有在虚拟场景中他附近的玩家。当很多人(超过 50 人)在一起时,就有大量的数据包需要广播出去。我们目前的做法是基于这样一个假设:服务器内部数据包的传递非常廉价。广播包比逐个发送更加廉价,这是因为,单机内部广播,可以避免大量的数据复制。所以,在同一张地图上,我们会简单的把任意一个 Agent 的状态改变信息广播给同张地图的所有其他人。这样就不需要动态维护分组信息。当每个 Agent 收到广播包后,再根据自身的逻辑进行过滤,再发给对应的客户端。
或许我们需要一个更为高效的广播方案,避免一些无谓的包复制。
我想实现这样一个数据结构: