9.14GTA Online's six-minute load
A player profiled GTA Online's released binary from outside and found two quadratic loops in its loading code, a JSON (JavaScript Object Notation) parse and a duplicate check, that together cost most of a six-minute load.
- 1Read
- Blast radius
- Players of GTA Online on PC, every time they loaded into the online game. On the author's machine the online load took about six minutes, with one processor core maxed out for about four of them.
- Duration
- Sixteen days from the write-up to the fix: the post was published on 28 February 2021, and Rockstar's title update with improved PC loading times followed on 16 March 2021. How long the slow load had existed before that is not stated in the sources used here.
- 2Follow
What happened, in order
- Then
On an AMD FX-8350 with a solid-state drive, t0st times GTA Online at about 6 minutes from the Rockstar logo to in-game, against about 1 minute 10 seconds for story mode.
- Then
Task Manager shows one CPU (processor) core at full load for about four minutes, with no disk, network or GPU (graphics processor) activity. A stack-sampling profiler, Luke Stackwalker, finds two hot spots, not one.
- Then
With no debug symbols and an obfuscated binary, t0st dumps the running game's memory and reads the disassembly. The first hot spot is strlen, called through what he is fairly confident is sscanf, parsing a 10 megabyte JSON file of about 63,000 store catalogue items.
- Then
The second hot spot is a duplicate check that compares each item's hash, one by one, against every item already loaded.
- Then
He writes a DLL (dynamic-link library) that hooks both functions: it caches the length of the long string, and inserts items directly. The online load falls to 1 minute 50 seconds.
- 28 Feb 2021
He publishes "How I cut GTA Online loading times by 70%", with the proof of concept on GitHub. It reaches the top of Hacker News.
- 15 Mar 2021
t0st reports that Rockstar has confirmed a fix is coming and has awarded him US$10,000 through its bug bounty, as an exception to a programme usually reserved for security issues.
- 16 Mar 2021
Rockstar's title update notes list "Improvements to PC loading times", with thanks to t0st. On the same machine, his stopwatch reads about 1 minute 55 seconds.
- Then
- 3Find
Root cause
NoteThe first loop was hidden inside a library call. The loader read numbers out of the 10 megabyte JSON text with sscanf, a value at a time. Many C library implementations of sscanf call strlen on the input string first, and strlen walks every character until it finds the end. So reading each tiny value cost a pass over the rest of the 10 megabytes, and reading all of them cost a number of steps that grows with the square of the file size. In t0st's profile strlen alone took 22 percent of the samples.
The second loop was in the game's own code. Each of the roughly 63,000 items was checked against the list of items already stored, entry by entry, before being added. By t0st's count that is (63,000 squared plus 63,000) divided by two, about 1.98 billion comparisons. The structure held hashes but was a plain array, "clearly not_a_hashmap", in his words; it started empty, every item in the file was unique, and the game already had a function to insert items directly.
Fixing either loop helped. With only the duplicate check patched the load took 4 minutes 30 seconds; with only the parser patched, 2 minutes 50 seconds; with both, 1 minute 50 seconds, a 69.4 percent improvement on his machine.
Two pieces of work that grew with the square of the catalogue, and how much of the six minutes each one cost on t0st's machine. - 4Trace
Why it got through
Both loops are linear work repeated inside a loop, so they are cheap when the data is small and get worse with the square of its size. A catalogue that is small when the code is written gives no sign of trouble, and the code that runs a strlen per value looks like one ordinary sscanf call. Nothing about the code reads as slow; only measuring the running program shows where the time goes.
Measuring was all it took. t0st had no source code, no symbols and an obfuscated binary, and found both problems with Task Manager, a profiler that had not been updated in over ten years, and a disassembler. The evidence pointed at one core doing one thing for four minutes. The sources do not say what Rockstar measured internally, so this page does not guess why its own profiling did not catch it.
- 5Check
The lesson
Profile before you guess, and treat every library call inside a loop as a loop of its own. Work that grows with the square of the input hides in plain sight until the input grows.
- 6Change
What changed afterwards
Rockstar's Title Update 1.53 notes, under 16 March 2021, list "Improvements to PC loading times" and thank t0st for his contributions. Rockstar gave no figure and no technical detail, and t0st writes that it could not share more.
Rockstar paid t0st US$10,000 through its HackerOne bug bounty, by his account as an exception, since the programme usually covers only security issues. His proof of concept, hardcoded for one game version, is archived with the note that Rockstar officially fixed the problem on 16 March 2021.
- 7Verify
Where the sources differ
- The 70 percent in the title is 69.4 percent in t0st's own arithmetic: about 6 minutes cut to 1 minute 50 seconds, on an AMD FX-8350. After Rockstar's update his stopwatch screenshot reads 1:54.88.
- That the parse calls sscanf is t0st's inference from the disassembly ("fairly confident it's sscanf"), not something Rockstar confirmed. The duplicate check is often described as a hash map scanned linearly; t0st says it was not a hash map at all, but an array of hash and item pointers.
- Rockstar confirmed the finding to PC Gamer, as PC Gamer reported, and its own notes thank t0st. The US$10,000 and the bounty being an exception come from t0st, and Rockstar published no figure.
- A common telling credits Ghidra. t0st used an unnamed disassembler, Process Dump to dump the obfuscated binary and x64dbg for data samples. The sources used here do not say how long the slow loading had existed, so this page does not say it lasted years.
- 8Source
Sources
- Primaryt0st, How I cut GTA Online loading times by 70% (28 February 2021)
- PrimaryRockstar Games, GTAV Title Update 1.53 Notes (PS4 / Xbox One / PC)
- Primaryt0st, GTAO_Booster_PoC (GitHub)
- AnalysisPC Gamer, GTA Online load time fix released, shaves off actual minutes of waiting for some
- DiscussionHacker News, How I cut GTA Online loading times by 70%
- 9Go