乐趣区

关于ide:打开游戏要运行-198-亿次-if-语句黑客嘲讽-RockStar-游戏代码太烂了

转自:量子位

一支烟的功夫,GTA 5 联机版 终于关上了。

「7 年了!GTA 5 联机版加载还是这么慢??」


*Please wait forever to play

Reddit、Steam、HackerNews 上,有数玩家吐槽埋怨……

进游戏少则等 5、6 分钟,多则 20 分钟。

终于,一个黑客大哥切实忍不了,用逆编译器逐条查看运行状况,终于找到起因。

原来,R 星(游戏开发商 RockStar)写的代码太低效,加载时,一个 if 语句居然循环了 19.8 亿次….

幕后黑手:谁占用大量工夫?

加载 GTA 5 Online 到底有多慢?

硬件拉满的土豪玩家请忽视

Reddit 相干板块发动的考察中,超过 80\% 的玩家,都要等 3 分钟以上,有的甚至超过 15 分钟。

而且,从 7 年前 Online 上线到明天,这个状况丝毫没有改善。

火暴的,曾经骂起了脏话……

但奇怪的是,如果你抉择是故事模式(单机版),加载就会快很多,感觉甚至像两个不同的工作室开发的游戏。

具体到这位黑客大哥的例子,他本人的硬件配置如下:

CPU,是老而弥坚的 AMD FX-8350,2012 年上市,采纳“推土机”架构,超频后劲惊人。

显卡还是 GTX 1070。

这样明天看起来老旧的配置,关上单机版 GTA 5 须要 1 分 10 秒,而加载联机版则 6 分钟起。

黑客大哥用了最简略的 Windows 工作管理器,来判断联机版 GTA 5 在启动时,都调用了哪些计算机资源。

在 1 分钟的工夫分界线上,之前是加载的是单机和联机版通用的根底内容,之后是联机版独有的内容。

能够看到,联机版 GTA 5,加载时调用大量 CPU 资源至多长达 4 分钟之久。

而同时,内存、GPU、硬盘的应用状况简直没有显著变动。

所以,问题大概率出在代码上。

“R 星代码写太烂!”

黑客大哥在开扒 R 星代码之前,就说:

我闻到一股烂代码的滋味…..

为了找出到底那一部分程序卡住了 CPU,他应用了工具Luke Stackwalker,对 CPU 工作堆栈进行采样剖析。

Luke Stackwalker 对于闭源应用程序,能够转存正在运行的过程堆栈,和以后指令指针的地位,以肯定工夫距离建设一个调用树。

最初将数据整合,就能够失去程序运行统计数据。

从后果上看,一共有两个函数“卡住”了 CPU:

于是他应用业余的代码拆解工具,给 GTA 5 来了一个“开膛破肚”。

沿着调用栈往下走,发现问题出在一个 sscanf 函数上。

sscanf 的性能是读取格式化的字符串中的数据,而在 GTA 5 中,它正在读取的是一个 10M 左右,有 63000 多个条目标 JSON 文件。

这个文件到底是干什么用的?黑客大哥揣测,这可能是 游戏内购商店的相干内容。

在具体运行时,sscanf 对于每个有效值,一一读取每一个字符,而后返回后果,之后指针移向下一个值,周而复始……直到把 10M 文件全副扫一遍。

再看第二个问题,这是一个存储命令,对象是item,具体是什么不得而知。

然而保留前,有一个 if 语句,逐个比拟 item 内我的项目的哈希值,查看它们是否呈现在某一列表中。

依照他的计算,这一步 if,要执行 (63000^2+63000)/2 = 1984531500 次!

没错,期待加载前的十多分钟里,GTA 5 用你的 CPU,执行了 19.8 亿次 if 命令。

如此简略粗犷的编程思路,让这位老哥啼笑皆非:

既然对象有惟一哈希值,那为什么不必hash map???

(hashmap 依据 hashCode 值存储数据,大多数状况下能够间接定位到它的值,因此具备很快的访问速度,但遍历程序不确定。)

问题解决,加载工夫节俭 70\%

至于第一个问题,黑客大哥采纳 hook 大法,不一一读取字符串,而是:

hook strlen
“缓存“字符串起始和以后长度。
如果在字符串范畴内函数在此被调用,返回缓存的值

至于 if 语句问题,就更间接了——齐全跳过反复查看,利用 hash map 插入我的项目,因为这些值是惟一的。

最初的后果如下:

当初,GTA 5 联机版加载,从原来的 6 分钟,降落到当初的 1 分 50 秒!而且,用的还是七八年前的硬件配置。

在此,应该手动 \@R 星:你学废了吗?

这位黑客大哥在博文中没有留下任何身份信息,也没有走漏用的反编译工具,然而做好事不留名的他,把打好包的工具上传到了 Github,玩家通过一行代码就能下载:

git clone —recurse-submodules https://github.com/tostercx/GTAO_Booster_PoC

之后,把 dll 文件粘贴到游戏根目录下就 OK!

博客原文
https://nee.lv/2021/02/28/How…

Github 地址:

https://github.com/tostercx/GTAO\_Booster\_PoC

开源前哨 日常分享热门、乏味和实用的开源我的项目。参加保护 10 万 + Star 的开源技术资源库,包含:Python、Java、C/C++、Go、JS、CSS、Node.js、PHP、.NET 等。

退出移动版