技术开发 频道

Erlang 性能优化总结

  【IT168 技术】作者主要从事游戏后端开发,所以本文只从游戏开发角度分析Erlang使用中应注意的问题和优化点。Erlang是一种通用的面向并发的编程语言,它由瑞典电信设备制造商爱立信所辖的CS-Lab开发,目的是创造一种可以应对大规模并发活动的编程语言和运行环境。Erlang问世于1987年,经过十年的发展,于1998年发布开源版本。Erlang是运行于虚拟机的解释性语言,在编程范型上,Erlang属于多重范型编程语言,涵盖函数式、并发式及分布式。顺序执行的Erlang是一个及早求值, 单次赋值和动态类型的函数式编程语言。

  1.单节点还是多节点

  Erlang节点之间的通信是透明的,节点内部和外部之间的调用一致。基于这样的特性,很多人会选用多节点,把各子系统(登陆节点,玩家节点,地图节点,全局节点等)分配到不同的节点中,以支持更多的在线玩家。这样做的出发点是好点是好的,但会引起一列表的问题:登陆、转场逻辑复杂,节点间的消息广播频繁,玩家数据同步、一致问题,内存消耗,运维复杂化等。相比之下,单节点就简单多了,不用考虑节点通信,玩家数据保证一致,运维方便,一机多服。在开启SMP的情间下,单节点的性能已经很好。对页游的业务,同时在线达到5000人已经非常少见,即使达到也是首服当天才会出现,单节点完全可以应付这样的情况,所以没必要用多节点,增加系统复杂性。

  2. 消息广播

  消息广播是游戏中的性能消耗大头,主要包括地图的行走、PK广播,世界聊天广播。世界聊天广播可以通过CD等策划手段限制,行走和PK包的广播实时性高,只能通过技术手段解决。地图中的广播包,只需发给视野内的玩家就可以,不用全地图广播。视野内的玩家可以通过九宫格划分,以 X,Y为主键,映射到对应的玩家数据。以九宫格方式查找玩家非常高效,我第一个游戏,地图中的玩家起初是保存在一个列表中,每次广播时都要遍历列表,找出同屏玩家,消息广播非常低效,特别是在PK时,CPU占用高。用九宫格优化后,一切问题都解决了。还有一个优化广播问题的方法是数据包缓存。

  3. 缓存-数据库,网络

  缓存是用空间换时间,它是性能优化中常用的方法。数据库缓存,开服时把玩家的必要数据加载到内存中,可以减少玩家的登陆延时,应对玩家并发登陆,刷新也很有效。同时玩家数据没必要实现存库,对于坐标,经验,金钱等变化频繁的值,如果实时存在,会很容易压跨数据库或对存库进程造成消息阻塞。玩家改变的数据可以缓在内存中,定时存库,或下线时再存库。网络中的消息包也可以在应用层给缓存起来,达到一定长度或延时一定时间后再发出去。虽然虚拟机和TCP层会做缓存,最好还是在应用层做一次缓存。

  4. 进程-每玩家应该有几个进程

  其实每玩家一个进程已经足够,代码简单,方便维护,性能开销小。没必要为每个玩家开启了网络,物品、任务等进程,多个进程不但造成进程间通信开销,还不好维护。

  5. 善用进程字典

  Erlang中是不建议用进程字典的,但进程字典是数据存取最快的方式,对于游戏这种高性能要求的应用,进程字典是不二的选择。使用进程字典时要切记在对应的进程中操作,最好按功能把put,get操作封装到模块接口中,避免误用。

  6. 代码规范

  a.代码应该简单,逻辑清晰,把功能细分到函数中。函数一般不多于30行,每个模块不多于1000行。

  b.写尾递归函数一定要有清淅的退出条件,不要在函数中改变退出条件。一个退出条件不明确的尾递归,是造成消息阻塞,内存耗尽的主要原因之一。

    %% 一个明确的尾递归函数:
    loop([H |T]) ->
        do_something,
        loop(T);
    loop([]) ->
        ok.

    %% 存在错误风险的写法
    %% NewLiist不可预期,存在死循环风险
    loop([H | T]) ->
        NewList = do_something(H,T),
        loop(NewList);
    loop([]) ->
        ok.

  c.不要相信客户端,上行的数据都需要验证,前端的请求都要做合法性判断,防止出现外挂、刷钱刷物品、刷金币的情况。

  d.不要写过多的case ,if嵌套,最好不要大于3个嵌套,通过 try catch 方法写扁平化的代码。

  7.自动化工具

  自动化工具可以避免出错,还把开发人员解放出来,提高生产效率。对于重复性,有规律的代码(如数据存取,通信协议),可以分离出来,让工具自动生成。有了生成工具后,修改协议,新加字段等操作,简单方便,不用为增加数据表中一个字段,而改十多个函数接口的修改;也不用担心前后端协议不一致的问题。

  8.监控系统

  通过erlang:system_monitor/2,监控系统long_gc,large_heap等情况。

  9.性能分析工具

  准备好top memory,top message_queue等查看系统属性的工具,出问题时可以随时查看。

4
相关文章