快速构建MMO服务器框架(五)timer的那些事儿

     定时器管理在MMO服务器这类需要处理大量事务的系统中,往往是优化的热点。
    最简单的轮询式定时器的实现如(psudo code):

    这种设计唯一的好处是编程方式简单。
    坏处:
    当需要检测的定时器大量增加时,整体性能将会严重下降。即使手动增加一些高精度把低精度计时器过滤掉的手法,也容易导致逻辑处理堆积在某个时间点的问题。
    诱导逻辑代码堆积在loop()函数中的不良风格。
    playerManager这类容器要时时防止遍历过程中添加、删除元素造成迭代器失效的情况,不过这是另一个问题了。

    对服务器而言,定时器逻辑的特性跟客户端的区别主要在于:客户端最主要操作是图形渲染,大部分对象每帧都要更新,对这些对象增加定时器调度机制也许还会得不偿失;时间间隔长的逻辑比较少,统一轮询处理也可接受。而服务器以大批量事务处理为主,时间间隔通常都在秒级以上,轮询会导致cpu大量空转。再者如果不能良好隔离各种事务逻辑,就会导致对象的更新函数中充满了各种如 if (task && taskTimer.check()) 这样的代码,难看且低效。
    
    而在boost中,提供了和io_service结合使用的deadline_timer类。同步的定时器会导致阻塞,用处不大,这里就不引用了。以下是异步定时器的示例:(出自boost文档)

    使用起来也很简洁。不过,异步的定时器也带来了复杂度上的增加,比如会牵涉到对象生命期的有效性之类,遇到这种情况可以结合智能指针使用。


细节和注意事项:

1.timer队列实现细节

    io_service内部有个timer_queue成员用来管理timer,不过并不是传统意义上的queue。timer在queue中有两个索引,一个是以timer地址作为索引的multi hashmap(概念上可以这么理解,实现上是hashmap + 链表),另一个是堆,按照触发时间由小到大排序,每次派发则执行 触发时间<当前时间 的timer回调。按照堆的性质,定时器添加进堆的复杂度是O(log n),不过大部分情况没那么坏(详细见下,出自wikipedia)

    If we have a heap, and we add an element, we can perform an operation known as up-heap, bubble-up, percolate-up, sift-up, or heapify-up in order to restore the heap property. We can do this in O(log n) time. (略)However, since approximately 50% of the elements are leaves and 75% are in the bottom two levels, it is likely that the new element to be inserted will only move a few levels upwards to maintain the heap. Thus, binary heaps support insertion in average constant time, O(1).

    timer的数据记录了在堆中的索引,删除也是O(log n)的时间复杂度(用来调整堆)。

    如果有大量timer高频率的插入和删除的需求,也许性能上会有影响。如果这种情况发生,可以在io_service的上层再自定制计时器管理机制。但切忌过早优化。

2.timer的生命期

    把timer添加到io_service中,实际上添加的不是timer对象本身,而是handler和时间信息。timer_queue内部对这些数据进行了包装,以timer的地址作为索引,但是并不会访问它所指的内存。所以如果在定时器触发前把timer对象删除,回调也会照常调用。可能出现的问题有:如果timer的内存回收,这段内存又刚好分配给new_timer,再把new_timer添加进io_service()中,此时调用io_service()移除new_timer则会把timer的回调也一起移除。如果需要严格确保这种情况不发生,则要控制好timer的生命期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值