游戏服务器设计的一些感悟

  • Author:Echo Chen(陈斌)

  • Email:[email protected]

  • Blog:Blog.csdn.net/chen19870707

  • Date:September 30th, 2014

        时间荏苒,转眼间已经做游戏一年了,第一款卡牌游戏《完美神话》也已经测试上线了,十一之后开始推广渠道,这一年经历了无数次崩服、回档、卡顿后,现在服务器终于基本稳定,对于程序员来说出问题是个好事情,只有在问题面前才能快速成长。在这里把这一年在服务器瓶颈中所入的坑做一个总结,希望对大家有帮助。

1.尽量减少内存拷贝

          memcpy对于服务器性能影响是很大的,下面给出memcpy的性能测试,可以看到在拷贝1M的时候已经用到0.7s,这对服务器性能影响是非常巨大的;此外,放入大量对象的容器在拷贝时,容器内对象都会进行拷贝构造,也非常消耗资源。

避免的方法:如果是大容量的容器,尽量的选择放入指针;

                     如果是收发缓冲区,可以选择环形队列,结合writev,readv 避免memcpy,实现高效收发;

拷贝size 消耗时间(微秒)
1k 350
10k 5502
100k 96624
1M 689399

2.避免大容器遍历

            遍历大容器是非常耗性能的,应该尽量避免。例如我们在设计消息系统的时候有个消息池,里面有10W的消息指针,之前未考虑到性能,每个玩家登陆都会来变量这个池,结果300个玩家上来CPU就到了100%,通过性能检测工具perf查到有80%的CPU时间都消耗在了遍历这个池上。

避免的方法:用时间换空间,巧用数据结构,用map、红黑树建立多维索引,尽量减少遍历。

3.尽力减少加锁

             多线程对锁的竞争是非常激烈的,加锁对性能的影响是非常巨大的,我们知道,单生产/单消费模式的共享队列是不需要加锁同步的(kfifo),所以尽量将多对一的队列拆分多个一对一的队列,这样就可以避免加锁了。例如我们的数据库是16个worker线程,如果公用一个队列必须加锁,势必竞争很激烈。我们对每一个worker线程维护了一个跟主线程的队列,这样就可以无锁访问了。

4.减少内存的分配和释放

              内存的频繁new 和delete不仅消耗性能,而且容易缠上大量的内存碎片  。对于游戏服务器而言,好的方法是用内存池,生成装备池、卡牌池、技能池等,不够时增量增加,如果需要释放,采用tcmalloc是一个不错的选择。

 

        目前能想到的就这么多,以后再继续补充,如果有什么错误和不明白的地方,欢迎大家指出。

-

Echo Chen:Blog.csdn.net/chen19870707

-

你可能感兴趣的:(多线程,游戏,线程,性能,内存)