ECS模型和服务器性能优化

 源码地址: https://github.com/ylmbtm/GameProject3

提到ECS模型,有不少的朋友己经很了解了,ECS模型据说是《守望先锋》那个团队成功使用后,才慢慢开始引起关注,说他们采用这种模型让客户端性能有了很大的提升,后来Unity引擎在后面的版本里也开始全面支持这种模式,有人用Unity做过对比,相较于原来的对象模型,采用ECS模型的代码性能提升很大,在更多同屏对象的情况下,还能保持更高的帧率,自此之后ECS影响越来越大,各种支持ECS模型的开发框架层出不穷,各种语言的都有,连Lua和typescript这种脚本语言都有专门的ECS框架,可见这种模型在提升程序的性能方面确实有不小的作用。

ECS模型相对对象模型其实并没有更先进的技术或者手段,仅仅是数据和逻辑的组织结构不同, 而就是这种结构的不同就带来了巨大的性能提升,这是怎么做到的呢?

要弄明白这个问题,我们首先要了解CPU缓存机制, 由于内存相对于CPU来说仍然是一个慢设备,为了弥补这种速度差,CPU内部就增加了有了缓存机制,现在的CPU一般都有三级缓存,分别是一级缓存(L1), 二级缓存(L2), 三级缓存(L3),CPU访问数据时并不是直接从内存中读取,而是首先查看L1中是否存在,没有则查看L2,L2没有则再查看L3,当L3也没有时则从内存中加载,越靠近CPU的缓存速度越快,反之就越慢, L1的访问速度最快,通常2-4个时钟周期,而内存最慢, 大约需要200-300个时钟周期。所以说如果我们能提高缓存的命中率,就能大幅提升程序的性能。

那ECS模型是如何有更高的缓存命中率呢, 这要来看看对象模型和ECS模型数据在内存中是如何组织的, 假设我们有一个对象,这个对象有三个模块数据,分别是A、B、C,现在我们创建出对象的三个实例,当我们用对象模型时,这三个对象在内存中的结构是这样的:

图片

而当我们用使用ECS模型时,这三个实例对象在内存中的结构是这样的:

图片

可以看到ECS模式下,同类型的数据紧密的排列在一起,这样数据被加载到缓存时,就能集中加载进更多的数据到缓存,从而极大的提升了缓存的命中率,也就提升了程序的性能。

这里讲到ECS模型,我并不认为服务器就需要全部采用ECS模型,在很多的情况,对象模型更符合人的思维习惯,开发也方便, 但我们仍然可以充分利用ECS的原理就是提高缓存命中率,来在服务器的开发中做一些针对性的优化。

首先, 我们可以尽量让需要集中访问的对象或者有遍历需求的对象在存储时用vector而不是用map。

比如说客户端连接的管理,我看过不少的框架都是用的map来管理,在我这个框架中我用了数组来管理,这样不光可以提高遍历时的性能,而且可以使用下标访问, 有比map的更快的访问速度。

其次有些用map管理的数据,底层也可以用连续的内存来实现。

我在框架里用到的对象池(MemObjectPool.h)和用AVL树(AVLTree.h)实现的一个map容器,底层都是用的连续内存来实现的,可以提高内存紧凑度也可以减少内存碎片。

当然有时候只是将对象在内存中更紧凑的排列仍然是不够的, 这仍然没有像ECS模型那么高效, 这种时候就需要部分采用ECS模式的思想, 比如说在下面这个情况:

假设在我们的一个服务器上有五千个玩家在线, 客户端和服务器采用状态同步的方式进行移动同步,在这种情况下客户端是不可能实时向服务器同步状态的,一般来说只有当然玩家,状态,方向,速度发生变化时才向服务器同步变化,而其它的时间,需要服务器根据玩家的状态,方向,速度进行自行更新。

基本上每一帧都需要遍历五千个玩家对象,来获取每个每个对象的方向,速度,坐标信息, 然后进行计算,然后更新坐标信息, 这个数据的访问压力是很大的,这个时候仅仅把玩家对象紧凑的排列在一起是不够的,因为一个玩家对象除了有以上这些信息外,还有血量,蓝量,装备数据,技能数据,阵营数据,骑乘数据,还在身上的buff数据等等。

我们假设一个玩家对象100个字节,那么五千个对象就大概需要500KB, 而一般服务器CPU的L1缓存的容量通常在32—256KB之间, 这意味着,无论如何紧凑,一级缓存也不可能全部装下, 一级缓存就无法全部命中。

如果我们把方向,速度和坐标这几个信息单独做为一个组件,用数组连续的存储起来,每个一组件不超过二十个字节,五千人,也只有10KB就可以装下,我们就很有可能在一次遍历更新的时候,在1级缓存全部命中,那么我们每帧的性能就大幅提升,必然可以提升服务器的承载人数。

其实提升缓存命中的方法很多,只要我们在开发过程合理的利用,就能提高我们程序的性能,也就能提高服务器的承载。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值