游戏服务器架构:基于匿名函数的高性能异步定时器系统

作者:码客(ygluu 卢益贵) 关键词:游戏服务器架构、匿名函数、高性能、异步定时器。

一、前言

本文主要介绍适用于MMO/RPG游戏服务端的、基于匿名函数做定时器回调函数的、高性能异步触发的定时器系统的设计方案,以解决常规线程loop-run-check模式的弊端。本文使用伪代码简明阐述理论。

二、系统框图

如图所示,本方案四大亮点

1、Main-Thread一直Wait-Msg(堵塞模式),抛弃了常规的线程loop-run-check模式,避免了无意义的Run、Sleep、业务Obj众多时的桶轮询机制,最大的发挥线程性能。

2、Timer-Thread仅根据interval来检查和触发,同一个interval的多个定时器只触发一次事件入列(第④步)。这样当定时器数量达到百万级的时候,第④步产生的消息队列数量非常少(因为游戏场景下的interval数值范围是有限的),减少了高频触发导致的线程锁和线程唤醒的性能消耗。

3、兼顾成员函数指针和匿名函数形式的定时器回调函数,开发更加简单便捷。

4、在异步线程触发消息的情况下,能保证定时器回调的安全性(定时器宿主Obj和关联上下文数据的安全性)。

三、时间轮设计(间隔时间)

时间精度:accuracy = 50 (单位毫秒,自定义常量)

预期间隔时间:interval

实际间隔时间(accuracy倍数): interval = interval / accuracy + accuracy * int( interval % accuracy > 0)

四、业务obj对象设计

class obj
{
    obj()
    {
        m_timer = new timer(mgr);
        // 成员方法指针方式触发定时器
        m_timer->open(start_time, interval, trigger_count, on_timer);  // 第①步
        // 匿名函数方式触发定时器
        m_timer->open(start_time, interval, trigger_count,    // 第①步
             []()
             {
              });
    };

    ~obj()
    {
        delete m_timer;
    };

    void on_timer()
    {
    };
};

五、定时器类设计

class timer
{
    timer(mgr)
    {
        m_mgr = mgr;
    };

    ~timer()
    {
        clear();
    };

    uint64 open(start_time, interval, trigger_count, std:function<void(void)> callback)
    {
        auto id = m_mgr(this, start_time, interval, trigger_count, callback);  // 第②步
        m_timer_ids.add(id);
        return id;
    };

    void clear()
    {
        for (auto id : m_timer_ids)
        {
            m_mgr->close(id);
        }
        m_timer_ids.clear();
    };

    close(id)
    {
        m_timer_ids.del(id);
        m_mgr->close(id);
    };
};
 

六、管理器类设计

class timer_mgr
{
    uint64 open(timer, start_time, interval, trigger_count, callback)
    {
        auto id = ++id_count;
        interval = interval / accuracy + accuracy * int( interval % accuracy > 0)

        auto info = {id, timer, create_time, last_time, start_time, interval, trigger_count, callback};
        // 根据触发间隔时间来分类管理定时器(回调函数)
        auto infos = infos_by_interval.find(interval);
        infos.add(id, info);

        // 告诉定时器线程增加触发间隔时间
        timer_thread->add(interval); // 第③步

        return id;
    };

    close(id)
    {
        auto info = info_by_id.find(id);
        auto infos = infos_by_interval.find(info->interval);
        infos.del(id);
        info_by_id.del(id);
    };

    // 第⑤步
    trigger(interval)
    {
        auto infos = infos_by_interval.find(interval);
        for (auto info: infos)
        {
            // 检查是否有延时启动时间
            if (info->start_time)
            {
               if (get_tick_count()- info->create_time < info->create_time)
               {
                   continue;
                }
                // 下次不再进入本分支
                info->start_time = 0;
            }            

            // call定时器回调函数 第⑥步
            info->callback();
 
            // 检查定时器寿命
            info->trigger_count++;
            if (info->trigger_count == 0)
            {
               info->m_timer->m_timer_ids->del(id);
               infos .del(id);
            }
        }

        // 告诉定时器线程删除触发间隔时间
        if (infos->size() == 0)
        {
             timer_thread->del(interval);  // 第步
        }
    };
};
 

七、定时器线程类设计

class timer_thread
{
    void add(interval)
    {
        lock();
        if (!m_intervals.find(interval)) 
        {
            m_intervals.add(m_intervals, {interval, get_tick_count()});
        }
        unlock();
    }

    void del(interval)
    {
        lock();
        m_intervals.del(m_intervals);
        unlock();
    }

    void check()
    {
        auto now = get_tick_count();
        for (auto info: m_intervals)
        {
             if (now - info->last_time) >= info->interval)
             {
                  info->interval = now;
                  m_main_queue.push(info->interval);  // 第④步
             }
        }
    }

    // 线程启动省略
};

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值