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

作者:码客(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);  // 第④步}}}// 线程启动省略
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无线液位监测技术在智能化时代的应用新趋势

在工业化进程日益加速的今天&#xff0c;对各类液体存储设施的有效监测与管理成为了保障生产安全、提高运营效率的关键环节。传统液位监测方式往往依赖于有线传感器&#xff0c;不仅安装维护复杂&#xff0c;而且受限于布线距离和环境条件&#xff0c;难以在复杂多变的工业场景…

minio 大视频观看,下载

在线观看 /*** 下载视频文件 fileName文件路径名称 文件路径 BacketName/video/1111.mp4 需要截取桶名后面的路径 video/1111.mp4 video前面不要带/ ** param fileName* param request* param response*/public void play(String fileName, HttpServletRequest request,…

Lianwei 安全周报|2024.08.26

新的一周又开始了&#xff0c;以下是本周「Lianwei周报」&#xff0c;我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件&#xff0c;保证大家不错过本周的每一个重点&#xff01; 政策/标准/指南最新动态 01 关于印发《全国重点城市IPv6流量提升专项行动工作方…

vue3模拟生成并渲染10万条数据,并实现本地数据el-table表格分页

效果图&#xff1a; 一点都不卡 话不多说&#xff0c;直接上码 <template><div class"container"><h3 class"table-title">el表格 分页</h3><el-table :data"tableList.slice((currentPage-1)*pageSize, currentPage*p…

Python测试框架Pytest的使用

pytest基础功能 pytset功能及使用示例1.assert断言2.参数化3.运行参数4.生成测试报告5.获取帮助6.控制用例的执行7.多进程运行用例8.通过标记表达式执行用例9.重新运行失败的用例10.setup和teardown函数 pytset功能及使用示例 1.assert断言 借助python的运算符号和关键字实现不…

Azure OpenAI citations with message correlation

题意&#xff1a;“Azure OpenAI 引用与消息关联” 问题背景&#xff1a; I am trying out Azure OpenAI with my own data. The data is uploaded to Azure Blob Storage and indexed for use with Azure AI search “我正在尝试使用自己的数据进行 Azure OpenAI。数据已上传…

ubuntu系统在线安装下载firefox-esr流览器

1、在线firefox流览器 Firefox ESR(Extended Support Release)是火狐浏览器的长期支持版本&#xff0c;针对同一个主版本提供一年左右的安全性与稳定性支持。如果您因为火狐浏览器改版而导致有原本能用的功能变得不能使用的话(例如Firefox 64.0把RSS订阅的功能拿掉了)&#xf…

VBA之正则表达式(46)-- 解析业务逻辑公式

实例需求&#xff1a;某业务系统的逻辑公式如下所示&#xff08;单行文本&#xff09;&#xff0c;保存在活动工作表的A1单元格中。 "DSO_90Day"->"FA_NoFunc"->"FCCS_No Intercompany"->"FCCS_Data Input"->"FCCS_…

SparkSQL数值模式详解

简介 函数如 to_number 和 to_char 确实支持在字符串类型和十进制&#xff08;数值&#xff09;类型之间进行转换。这些函数接受格式字符串作为参数&#xff0c;这些格式字符串指示了如何在这两种类型之间映射。 to_number&#xff1a;这个函数通常用于将字符串转换成数值类型…

在IDEA中使用Git

在IntelliJ IDEA&#xff08;通常简称为IDEA&#xff09;中使用Git进行版本控制是一种高效且集成度高的做法。以下是在IDEA中使用 Git的详细步骤和说明&#xff1a;一、安装与配置Git 安装Git&#xff1a; 前往Git的官方网站下载并安装Git。 安装过程中&#xff0c;建议勾选“…

泛微E9如何更新缓存

泛微E9如何更新缓存 在E9中&#xff0c;是默认开启了数据缓存的&#xff0c;如果直接操作数据库是会存在缓存不更新的问题&#xff0c;E9系统提供以下几种方式进行缓存清空的方式。 注&#xff1a;原则上禁止通过非程序渠道直接修改OA数据库数据&#xff0c;可以直接在页面进行…

flutter开发小技巧

Uri对象的使用 直接使用字符串来拼接 URI 地址需要关注地址中拼接的每个部分的合法性&#xff0c;并且在处理复杂逻辑时需要更冗长的处理&#xff0c;如果变量包含非法字符(如中文)&#xff0c;整个地址非法。 如&#xff1a;在路由跳转中使用 方式一&#xff1a;使用Uri对象…

clickhouse-neighbor 坑爹的排序

对于排序规则明显的数据集&#xff0c;使用neighbor来做分析&#xff0c;是一个非常强大的函数&#xff0c;能完成很多复杂的计算&#xff0c;例如高速公路分析车辆流量。 高速公路截面流量一般是通过路面上的门架采集设备采集通行卡的信息和识别牌照组成&#xff0c;在路面行驶…

Linux云计算 |【第二阶段】SECURITY-DAY3

主要内容&#xff1a; Prometheus监控服务器、Prometheus被监控端、Grafana监控可视化 补充&#xff1a;Zabbix监控软件不自带LNMP和DB数据库&#xff0c;需要自行手动安装配置&#xff1b;Prometheus监控软件自带WEB页面和DB数据库&#xff1b;Prometheus数据库为时序数据库&…

05:极限-无穷小

1.无穷小的概念及比较 定义&#xff1a; lim ⁡ x → x 0 f ( x ) 0 , 则称 f ( x ) 是 x x 0 时的无穷小 定义&#xff1a; \lim_{x \to x_0} f(x) 0,则称f(x)是xx_0时的无穷小 定义&#xff1a;x→x0​lim​f(x)0,则称f(x)是xx0​时的无穷小 性质Value①有限个无穷小相加还…

java 使用 aws s3 sdk 实现视频文件的分段下载来实现html 页面 video 的断点播放、拖动进度播放

参考博客&#xff1a; 1. Java 视频流分段返回 1. java 拉取 aws s3 视频流返回给浏览器&#xff1a; Overridepublic void playVideo(Long fileLength,String key,HttpServletRequest request,HttpServletResponse response) {OutputStream outputStream null;S3ObjectInputS…

JVM 运行时内存结构简介

JVM 运行时内存结构简介 一、前言二、JVM 运行时内存结构2.1 线程隔离数据区&#xff1a;2.2 线程共享数据区&#xff1a; 三、JVM 内存区域划分1. 程序计数器&#xff08;PC&#xff09;2. 虚拟机栈3. 本地方法栈4. Java 堆5. 方法区6. 运行时常量池 附录 一、前言 JVM&#…

【C#】【EXCEL】Bumblebee/Classes/ExColumn.cs

文章目录 Bumblebee/Classes/ExColumn.csFlow diagramDescriptionCode Bumblebee/Classes/ExColumn.cs Flow diagram #mermaid-svg-6WUm4r0wDJG9uelI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6WUm4r0wDJG9ue…

手撕C++类和对象(中)

1.类的默认成员函数 默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我 们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最 后两个取地址重载不…

Linux 内核源码分析---IPv6 数据包

IPv6是英文“Internet Protocol Version 6”&#xff08;互联网协议第6版&#xff09;的缩写&#xff0c;是互联网工程任务组&#xff08;IETF&#xff09;设计的用于替代IPv4的下一代IP协议&#xff0c;其地址数量号称可以为全世界的每一粒沙子编上一个地址。 由于IPv4最大的…