[情报] GTAO一个if语句循环19.8亿次 骇客嘲讽R星

楼主: egain (天国直达车)   2021-03-07 21:58:38
侠盗猎车手Online一个if循环19.8亿次,而且7年没人去修它,骇客顺手解决这个问题了
https://www.techbang.com/posts/84848-whats-the-worst-code-youve-ever-seen
https://reurl.cc/ynvVOM 一支菸的时间,侠盗猎车手Online终于打开了。
“7年了!GTA 5 Online加载还是这么慢??”
Reddit、Steam、HackerNews上,无数玩家吐槽抱怨……
进游戏少则等5、6分钟,多则20分钟。
终于,一个骇客实在忍不了,用反组译编辑器逐条查看运行情况,终于找到原因。
原来,R星(游戏开发商RockStar)写的程式码太没有效率,加载时,一个if语句竟然循
环了19.8亿次….
谁占用大量时间?
加载GTA 5 Online到底有多慢?
Reddit相关群组发起的调查中,超过80%的玩家,都要等3分钟以上,有的甚至超过15分钟

而且,从7年前Online上线到今天,这个情况丝毫没有改善。
脾气不好一点的,早就开始骂脏话……
但奇怪的是,如果你选择是故事模式(单机版),加载就会快很多,感觉甚至像两个不同
的工作室开发的游戏。
以这位骇客的例子,他自己的硬件规格如下:
https://reurl.cc/0DdNkK
CPU,是老而弥坚的AMD FX-8350,2012年上市,采用“推土机”架构,超频潜力惊人。显
示卡还是GTX 1070。
这样今天看起来老旧的配置,打开单机版GTA 5需要1分10秒,而加载Online版则6分钟起

骇客用了最简单的Windows任务管理器,来判断Online版GTA 5在启动时,都使用了哪些电
脑资源。
https://reurl.cc/bzYpeo
在1分钟的时间分界线上,之前是加载的是单机和Online版通用的基础内容,之后是
Online版独有的内容。
可以看到,Online版GTA 5,加载时调用大量CPU资源至少长达4分钟之久。
而同时,内存、GPU、硬盘的使用情况几乎没有明显变化。所以,问题有很大的机率是
出在程式码上面。
R星程式码写太烂!
骇客在开扒R星程式码之前,就说:我闻到一股烂程式码的味道…
为了找出到底那一部分程式卡住了CPU,他使用了工具Luke Stackwalker,对CPU任务堆栈
进行采样分析。
Luke Stackwalker对于闭源应用程式,可以转存正在运行的进程堆栈,和当前指令指针的
位置,以一定时间间隔建立一个调用树。
最后将数据整合,就可以得到程式运行统计数据。
从结果上看,一共有两个函数“卡住”了CPU:
https://reurl.cc/WEN9yL
于是他使用专业的程式码拆解工具,把GTA 5来了一个“开膛破肚”。沿着调用栈往下走
,发现问题出在一个sscanf函数上
https://reurl.cc/nnvgyD
sscanf的功能是读取格式化的字符串中的数据,而在GTA 5中,它正在读取的是一个10M左
右,有63000多个条目的JSON档案。
这个档案到底是干什么用的?这位老兄推测,这可能是游戏内购商店的相关内容。
https://reurl.cc/kVyAkn
在具体运行时,sscanf对于每个有效值,逐个读取每一个字符,然后返回结果,之后指针
移向下一个值,循环往复……直到把10M文件全部扫一遍。
再看第二个问题,这是一个存储命令,对像是item,具体是什么不得而知。
但是保存前,有一个if语句,逐一比较item内项目的哈希值,检查它们是否出现在某一列
表中。
按照他的计算,这一步if,要执行(63000^2+63000)/2 = 1984531500次!
没错,等待加载前的十多分钟里,GTA 5用你的CPU,执行了19.8亿次if命令。
如此简单粗暴的编程思路,让这位老哥哭笑不得:
既然对像有唯一杂凑函式,那为什么不用hash map???
hashmap根据hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快
的存取速度,但遍历顺序不确定。)
至于为什么这样,有网友推测最开始,if的循环次数并没有这么多,而是随着开发,条目
不断增多,最后到了积重难返的地步。
而之前的程式码结构,谁也不愿意去动。
就这样,19.8亿次if,一遍遍在世界各地玩家cpu上上演.....
至于第一个问题,骇客采用hook大法,不一一读取字符串,而是:
hook strlen
“快取”字符串起始和当前长度。
如果在字符串范围内函数在此被调用,返回快取的值。至于if语句问题,就更直接了——
完全跳过重复检查,利用hash map插入项目,因为这些值是唯一的。
最后的结果如下:
https://reurl.cc/NXleDp
现在,GTA 5Online版加载时间,从原来的6分钟,下降到现在的1分50秒!而且,用的还
是七八年前的硬件规格。
在此,应该手动@R星:你学废了吗?
这位骇客在文章中没有留下任何身份讯息,也没有透露用的反组译工具,但是做好事不留
名的他,把打好包的工具上传到了Github,玩家透过一行程式码就能下载:
git clone —rec
作者: k960608 (雾羽‧浪沙)   2021-03-07 22:00:00
恩恩跟我自己发现的结果很像
作者: willytp97121 (rainwalker)   2021-03-07 22:04:00
真骇客本色
作者: linzero (【林】)   2021-03-07 22:05:00
听起来一开始资料少时比对资料,官方方式也很快所以没差
作者: a204a218 (Hank)   2021-03-07 22:05:00
程式码这种东西有时候硬修反而跑出更多莫名其妙的BUG,于是只能将就著能跑就行
作者: linzero (【林】)   2021-03-07 22:06:00
但资料一多后,官方的笨方式就会很慢
作者: kaj1983   2021-03-07 22:06:00
好奇R星这次还会大刀开铡吗?
作者: linzero (【林】)   2021-03-07 22:07:00
但有时BUG这东西,你不知道改一个会不会又跑出另一个甚至多个。尤其是这程式之前是其他人开发的所以不严重的优先排序比较后面,或者根本不管他
作者: Ricestone (麦饭石)   2021-03-07 22:08:00
上一篇有人说被封锁了
作者: linzero (【林】)   2021-03-07 22:08:00
而严不严重,有时也是很主观的
作者: spfy (spfy)   2021-03-07 22:10:00
上一篇那个是真的吗 找了一下好像没有其他案例?
作者: backzerg (Blackzerg)   2021-03-07 22:10:00
BUG就跟史莱姆一样 解完一个变两个 两个变四个
作者: kaj1983   2021-03-07 22:10:00
这个读取问题已经可以量化到用时间来评估了,R星应该主动修正这个问题,而且有人都帮你找好解了
作者: a8856554 (虚舟)   2021-03-07 22:12:00
看起来很像是储存的时候用了O(n^2)的方法,改用O(n)的hash map加速
作者: sawaman (賽媧)   2021-03-07 22:16:00
看不懂但觉得好屌=.=
作者: roy126809 (今天用右手)   2021-03-07 22:16:00
optimize ticket优先度很低 没人催的话通常会一直延我看过一张ticket放在那边两年没人做
作者: orze04 (orz)   2021-03-07 22:19:00
储存前会检查一次是否重复储存但你都有map了....
作者: abadjoke (asyourlife)   2021-03-07 22:38:00
我完全能理解 接受以前的人留下来的程式码后完全不想动反正跑得出来就好 效率什么的要去修有时还不如自己重写
作者: drazil (在风雨飘摇的年代里)   2021-03-07 22:42:00
同意楼上讲的,接手改别人写的程式码有时候真的很头痛程式架构的设计逻辑都不是自己的,真的会怕哪边想法没对到
作者: aegius1r (SC)   2021-03-07 22:45:00
不过loading 20分钟真的是发optimize不是issue吗XDD
作者: drazil (在风雨飘摇的年代里)   2021-03-07 22:46:00
然后不改还好,一改就改出大问题......
作者: zxc1020305 (理解不能)   2021-03-07 22:47:00
不改还不是一堆人玩,改了要是出bug谁负责。当事情牵涉到技术以外的层面就不是这么单纯的问题了
作者: roy126809 (今天用右手)   2021-03-07 22:52:00
有人催ticket topic就会变成issue了啊 没有就放给他烂不然通常是先弄新feature 反正跑的动
作者: smallreader (小读者)   2021-03-07 22:54:00
逐一比对hash谁写的 这种大学就要被当了吧弄hash竟然不懂hashmap
作者: DarkyIsCat (黑肉猫娘赞)   2021-03-07 23:11:00
真的有够久 我都等10分钟左右 开连线后就先去看影片了
作者: EZTW0000   2021-03-07 23:18:00
相比rdr2线上加载就很快
作者: BigGun5566 (大枪56)   2021-03-08 00:27:00
程式设计里有句老话,只要能动,就不要去改它
作者: ro22113175 (明月)   2021-03-08 00:46:00
真骇客就是要自己修程式 XD
作者: greed3819 (咬我啊笨蛋)   2021-03-08 04:29:00
能work就不要随便改他,程式设计必学的当debug的人跟当初开发的不是同一个人的时候
作者: s2327259 (史东)   2021-03-08 05:05:00
团体写code就是这样 你不会想动能跑的东西
作者: steven7851 (小天)   2021-03-08 07:02:00

Links booklink

Contact Us: admin [ a t ] ucptt.com