Python实战社群
Java实战社群
长按识别下方二维码,按需求添加
![640.webp (1).jpg](https://img.php1.cn/3cd4a/1e618/cd5/af17da15769ccb2e.jpeg)
扫码关注添加客服
进Python社群▲
![微信图片_20200223084351_副本.png](https://img.php1.cn/3cd4a/1eebe/cd5/d34245582687a4e6.webp)
扫码关注添加客服
进Java社群▲
贾浩楠 发自 凹非寺
量子位 报道 | 公众号 QbitAI
一支烟的功夫,GTA 5联机版终于打开了。
![](https://img.php1.cn/3cd4a/1eebe/cd5/7494af3c1cda418d.webp)
「7年了!GTA 5联机版加载还是这么慢??」
△Please wait forever to play
Reddit、Steam、HackerNews上,无数玩家吐槽抱怨……
进游戏少则等5、6分钟,多则20分钟。
终于,一个黑客大哥实在忍不了,用逆编译器逐条查看运行情况,终于找到原因。
原来,R星(游戏开发商RockStar)写的代码太低效,加载时,一个if语句竟然循环了19.8亿次….
幕后黑手:谁占用大量时间?
加载GTA 5 Online到底有多慢?
![](https://img.php1.cn/3cd4a/1eebe/cd5/1113165c4904ecc5.webp)
△硬件拉满的土豪玩家请无视
Reddit相关板块发起的调查中,超过80%的玩家,都要等3分钟以上,有的甚至超过15分钟。
而且,从7年前Online上线到今天,这个情况丝毫没有改善。
暴躁的,已经骂起了脏话……
![](https://img.php1.cn/3cd4a/18ace/696/1d8e759bd3e6bbec.jpeg)
但奇怪的是,如果你选择是故事模式(单机版),加载就会快很多,感觉甚至像两个不同的工作室开发的游戏。
具体到这位黑客大哥的例子,他自己的硬件配置如下:
![](https://img.php1.cn/3cd4a/1eebe/cd5/0a0ce631ec450943.webp)
CPU,是老而弥坚的AMD FX-8350,2012年上市,采用“推土机”架构,超频潜力惊人。
显卡还是GTX 1070。
这样今天看起来老旧的配置,打开单机版GTA 5需要1分10秒,而加载联机版则6分钟起。
黑客大哥用了最简单的Windows任务管理器,来判断联机版GTA 5在启动时,都调用了哪些计算机资源。
![](https://img.php1.cn/3cd4a/1eebe/cd5/1e3db12dd78db092.webp)
在1分钟的时间分界线上,之前是加载的是单机和联机版通用的基础内容,之后是联机版独有的内容。
可以看到,联机版GTA 5,加载时调用大量CPU资源至少长达4分钟之久。
而同时,内存、GPU、硬盘的使用情况几乎没有明显变化。
所以,问题大概率出在代码上。
“R星代码写太烂!”
黑客大哥在开扒R星代码之前,就说:
我闻到一股烂代码的味道…..
为了找出到底那一部分程序卡住了CPU,他使用了工具Luke Stackwalker,对CPU任务堆栈进行采样分析。
Luke Stackwalker对于闭源应用程序,可以转存正在运行的进程堆栈,和当前指令指针的位置,以一定时间间隔建立一个调用树。
最后将数据整合,就可以得到程序运行统计数据。
从结果上看,一共有两个函数“卡住”了CPU:
![](https://img.php1.cn/3cd4a/1eebe/cd5/43a754c811e7ec5c.webp)
于是他使用专业的代码拆解工具,给GTA 5来了一个“开膛破肚”。
沿着调用栈往下走,发现问题出在一个sscanf函数上。
![](https://img.php1.cn/3cd4a/1eebe/cd5/0a0ce631ec450943.webp)
sscanf的功能是读取格式化的字符串中的数据,而在GTA 5中,它正在读取的是一个10M左右,有63000多个条目的JSON文件。
这个文件到底是干什么用的?黑客大哥推测,这可能是游戏内购商店的相关内容。
![](https://img.php1.cn/3cd4a/1eebe/cd5/a5d7215df572c386.webp)
在具体运行时,sscanf对于每个有效值,逐个读取每一个字符,然后返回结果,之后指针移向下一个值,循环往复……直到把10M文件全部扫一遍。
再看第二个问题,这是一个存储命令,对象是item,具体是什么不得而知。
但是保存前,有一个if语句,逐一比较item内项目的哈希值,检查它们是否出现在某一列表中。
按照他的计算,这一步if,要执行(63000^2+63000)/2 = 1984531500次!
没错,等待加载前的十多分钟里,GTA 5用你的CPU,执行了19.8亿次if命令。![](https://img.php1.cn/3cd4a/1eebe/cd5/60405fda58cd0acd.webp)
如此简单粗暴的编程思路,让这位老哥哭笑不得:
既然对象有唯一哈希值,那为什么不用hash map???
![](https://img.php1.cn/3cd4a/1eebe/cd5/1113165c4904ecc5.webp)
(hashmap根据hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序不确定。)
问题解决,加载时间节省70%
至于第一个问题,黑客大哥采用hook大法,不一一读取字符串,而是:
hook strlen
“缓存 “字符串起始和当前长度。
如果在字符串范围内函数在此被调用,返回缓存的值
至于if语句问题,就更直接了——完全跳过重复检查,利用hash map插入项目,因为这些值是唯一的。
最后的结果如下:
![](https://img.php1.cn/3cd4a/1eebe/cd5/a1be7872e8d4934f.webp)
现在,GTA 5联机版加载,从原来的6分钟,下降到现在的1分50秒!而且,用的还是七八年前的硬件配置。
在此,应该手动@R星:你学废了吗?![](https://img.php1.cn/3cd4a/1eebe/cd5/5287a7b3296ea13e.webp)
这位黑客大哥在博文中没有留下任何身份信息,也没有透露用的反编译工具,但是做好事不留名的他,把打好包的工具上传到了Github,玩家通过一行代码就能下载:
git clone —recurse-submodules https://github.com/tostercx/GTAO_Booster_PoC
之后,把dll文件粘贴到游戏根目录下就OK!
博客原文
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/
Github地址:
https://github.com/tostercx/GTAO_Booster_PoC
— 完 —
本文系网易新闻•网易号特色内容激励计划签约账号【量子位】原创内容,未经账号授权,禁止随意转载。
![](https://img.php1.cn/3cd4a/1eebe/cd5/70be2ca197098d98.webp)
程序员专栏 扫码关注填加客服 长按识别下方二维码进群
![](https://img.php1.cn/3cd4a/1eebe/cd5/8be1ccb5166feb93.webp)
近期精彩内容推荐:
华为正式宣布养猪,网友:支持华为自救!
入职腾讯第九年,我辞职了!
Windows蓝屏为什么是蓝底白字?
955 互联网公司白名单来了!
![](https://img.php1.cn/3cd4a/1eebe/cd5/a1be7872e8d4934f.webp)
![](https://img.php1.cn/3cd4a/1eebe/cd5/d942b7ec373849c3.webp)
在看点这里
好文分享给更多人↓↓