惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MongoDB | Blog
MongoDB | Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
NISL@THU
NISL@THU
AWS News Blog
AWS News Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Privacy & Cybersecurity Law Blog
S
Schneier on Security
PCI Perspectives
PCI Perspectives
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Troy Hunt's Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
Know Your Adversary
Know Your Adversary
F
Fortinet All Blogs
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
Jina AI
Jina AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
WordPress大学
WordPress大学
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
T
Tor Project blog
S
Security Affairs
S
Securelist
F
Full Disclosure
D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
Martin Fowler
Martin Fowler
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
Apple Machine Learning Research
Apple Machine Learning Research
N
News and Events Feed by Topic
Recorded Future
Recorded Future
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
Stack Overflow Blog
Stack Overflow Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
I
Intezer
Security Latest
Security Latest
Scott Helme
Scott Helme
U
Unit 42
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog

重归混沌的BLOG

给silly实现了一个ernro模块 | 重归混沌的BLOG 给silly实现了一个ernro模块 | 重归混沌的BLOG 第一次在生产环境使用 Vibe Coding | 重归混沌的BLOG 第一次在生产环境使用 Vibe Coding | 重归混沌的BLOG API 设计的艰难抉择 | 重归混沌的BLOG API 设计的艰难抉择 | 重归混沌的BLOG 十年 | 重归混沌的BLOG 十年 | 重归混沌的BLOG 在Go语言中如何使XML加载内存无限趋近于0 | 重归混沌的BLOG 在Go语言中如何使XML加载内存无限趋近于0 | 重归混沌的BLOG 对跨服玩法中的分布式一致性问题进行简单抽象 | 重归混沌的BLOG 对跨服玩法中的分布式一致性问题进行简单抽象 | 重归混沌的BLOG Go语言逃逸分析之slice和map | 重归混沌的BLOG Go语言逃逸分析之slice和map | 重归混沌的BLOG 谈谈观测 | 重归混沌的BLOG 谈谈观测 | 重归混沌的BLOG 写了个AI Agent服务端 | 重归混沌的BLOG 写了个AI Agent服务端 | 重归混沌的BLOG 谈谈代码设计中“严丝合缝” | 重归混沌的BLOG 谈谈代码设计中“严丝合缝” | 重归混沌的BLOG 一次艰难的线上游戏服务器内存排查经历 | 重归混沌的BLOG 一次艰难的线上游戏服务器内存排查经历 如何基于LanguageServerProtocol来编写lint工具 谈谈游戏服务器中RPC模块的设计 谈谈游戏服务器代码抽象 最近碰到的一个分布式一致性问题 谈谈游戏服务器的自动化测试 对Raft协议的一点理解 使用mmap来学习/proc/pid/smaps 2023(完) 再次实现了一个Lua性能分析器 终于给Silly的定时器增加了取消功能 一次虚拟内存排查经历 游戏服务器分布式数据的一种同步的思路 为silly增加了互斥锁 2022(完) Go语言之闭包篇 一例误用unsafe包引起的内存问题 Go语言之内存篇 初识Go语言 重新抽象图形API 给Lua实现了一个数学库 谈谈跨平台图形API的抽象 寻路和Flocking算法的结合 行为树的一种高效实现 内测过程中Shader出现的问题 彻底解决多国语言 谈谈数据库的选型 再谈Lua热更新(终) 初窥Rust 关于游戏服务器的服务拆分 ECS的初步实现 ECS初探 屏幕空间(SreenSpace)的想象力 一些对辐射度量学的理解 深度缓冲和半透明渲染 Mysql的间隙锁 更新一些GPU相关知识 2020 地形渲染之爬过的坑 Lua5.3 GC源码阅读(5) 实现一个数据库存储队列 再学计算机图形学入门 再谈分布式服务架构 游戏上线一个月后的反思 一次并发Bug 双向链表的三种实现 谈谈随机数的使用 2019 Lua中的函数式编程 重构登录逻辑 Unity资源管理(续) 谈谈Unity的资源管理 一次关于Cache的性能分析 历史之2018 DC3算法 移动平台native代码遭遇的坑 从CPU层面谈谈优化 开卷有益(UNIX编程艺术篇) GC竞争问题 通过Mesh投影来实现贴花系统 谈谈我对数据同步的理解 又一个类型提升引起的Bug Lua5.3 GC源码阅读(4) Lua5.3 GC源码阅读(3) Lua5.3 GC源码阅读(2) Lua5.3 GC源码阅读(1) 三角形光栅化时遇到的坑 一次git事故 再见2017 又一个lua调试器 客户端缓存落地方案 Paxos算法 HTTP服务器的特点 一次性能优化经历 关于CPU分支预测 C程序中让两个不同版本的库共存 实现了一个AOI模块 一个高可伸缩的游戏服务器架构 关于网络协议封装的一些新想法
再谈性能优化
重归混沌 · 2020-02-29 · via 重归混沌的BLOG

版本开发终于接近尾声了,最近在做一些扫尾(性能优化)工作。老实说,这是我第一次细致的测量业务逻辑的性能。

我曾一度以为游戏服务器是io密集型程序,cpu其实很轻,至少对于一般的卡牌游戏应当如此。

虽然天天跟策划㗏㗏性能,但是那仅仅只是为了追求更好性能而已。

我们的服务器程序有10w+的echo能力,再加上我写逻辑从来都是按我知道的性能最高的方式写,所以我从不认为有一天会有处理请求过慢的问题,也从来没有思考过这个问题。

这次测试深深的给我上了一课。

在最初的版本中,一个普通五连抽,竟然要花2+ms,也就是说一秒竟然只能抽500次不到。

这也意味着一个服务器,只要不到500个人同时抽一次五连抽,服务器就卡爆了。就这,还没有统计网络处理的开销。

10万和500的巨大差距是我从来都没有想过的。

带着难以置信的心情,我开始使用valgrind进行性能分析,并一个一个的解决热点。

第一次定位到最大的开销竟然是log。

我看了一下源码,发现为了可以方便的定位问题,我们几乎每个函数都有log。有些函数在条件不满足(也就是什么都不执行)的情况下,依然会打一行log代表自己处理过。

我把所有逻辑都修改为不产生副作用时不输出log。毕竟函数是否进入,可以通过caller的逻辑来确定,相信caller会有相关的log。

而一旦可以确认一个函数被调用,如果没有log输出,本身就可以代表一种状态(函数不满足执行条件)。我认为这应该算是一种比较好的折中了。

修改了log之后,紧接着的热点就是货币管理。

在招募过程中会有若干个子过程,分属不同的模块。这些模块又会分别扣钱和加钱,由于逻辑相关性和KISS原则。我们不会在逻辑中将’扣钱’和’加钱进行合并操作’。

而且,为了保证可靠性,每次进行货币操作,都会进行数据库存储操作。

存数据库前,我们一般是先将一个struct序列化成string。然后进行存储,并打一行log。

根据valgrind显示,此次货币管理模块的热点问题就是存储数据库相关的函数造成的。其中log部分的开销占了一大部分。

我采用了之前文章里提到的关键点存库的方式,将货币模块的储存降到了每个客户端请求只存储一次数据库的频率。

优化货币模块本来最简单的应该是,直接删掉存数据库时的log, 毕竟log占了一大部分的开销。

但是本着最高性能的原则我还是修改了货币的存储频率。这样可以节省一部分数据库的开销。

做完以上这些修改之后,重新测了一下。

已经可以在不开O2的情况下达到800+次请求。开了O2之后可以达到1200+次请求。

继续用valgrind分析,发现代码已经开始均匀的变慢,并没有什么明显的特征。

按说这时候想再提高处理速度就只有换CPU了,但是我察觉到相关代码中均匀的分布着C++的unordered_map类。

联系到,上次优化战斗时,我牺牲了3k内存直接将使用最频繁的一个unordered_map换成数组时,性能翻了2到3倍。我觉得如果应该还有优化的余地。

但是,并不是所有的数据都可以使用数组来替换的,这些业务逻辑需要的是一个更好更快的hash_table。如果想要进一步优化,就只能找一个第三方hash table(比如把lua的借过来)来替换掉unordered_map。

但是扫尾工作,我不太想做这么大的的改动。现阶段这个请求处理速度已经勉强可以达到要求了。毕竟不是所有玩家都是土豪^_^。

我以前说过:“底层逻辑的开销会被上层逻辑放大”,这是对框架说的。现在看起来需要修正为:“被依赖模块的开销,会被所有依赖他的模块放大”。

就这次优化经验来看,有时候所有模块都有高性能的实现,不代表整体性能就高。整体框架或机制的设计,会成为制约着整体性能的瓶颈。

这就要求在以后设计框架或机制时,不仅要做到自身效率高,还要考虑在上面实现业务逻辑时,是不是可以高效的实现。好的框架或机制对业务逻辑的性能是有导向意义的。

ps. 以往优化都是局限在某一个系统或模块。而这次优化引导着我从全局来看整个逻辑,这是一种从未有过的体验。