CreatorsOk
vrengames
vrengames

patreon


Temporary Optimization Defeat

Following the release of v0.15.1 I've received a few reports that the game is proving to be very slow to load on some machines. Particularly strange are reports that starting the game from the generated build is painfully slow but starting it from the Ren'py launcher is silky smooth. I've noticed on my own machine that it can take a minute or so to launch the game or reinitialize it when testing, so I decided it was time to nail down this problem and solve it once and for all. If only it ended up being that easy.

The first step to solving any problem is to define what the problem is in the first place. Qualitatively Lab Rats 2 was taking too long to load, but "too long" is a subjective thing and I wanted hard data. After a few cycles starting and quitting the game on my own machine I had a baseline startup time of 1:17 from the moment I hit "Launch" to the main menu appearing. With that knowledge I set off looking for likely problems that would be causing the slowdown.

My first assumption was that the cause of the slowdown would be somewhere inside my own initialization code, looping over too many clothing items  or something of that nature. Renpy code that is run at initialization is all given a priority number and then run from lowest to highest. Instead of going through all of my code line by line I decided to narrow down the search by identifying which init phase was taking the longest. I added some extra init code sprinkled between init -5 to 5 (the priorities inside of which all my code is run) that would log when that phase was reached and ran it to see what would be reported. Strangely, my log showed all of the watched phase being completed in under a second. I widened the range I was watching, going all the way up to init 999 - the documented limit for what the init numbers should be. The result was the same, no measured delay in running the code.

This was strange. There was a ~90 second delay when starting the game but no measured delay in my own code. I enabled some Ren'py debug logging and confirmed that the "running init" section was taking up 87 of the 90 second delay. On a hunch I expanded the range of my own init logging outside of the range suggested and discovered that the expected run time took place on init phase 1100. None of my code touches that part of the game, so there must be some internal Ren'py code that is running then. Thus began the multi-day hunt to determine what, exactly, was triggering this behaviour in Ren'py and how could it be avoided.

I did some more testing and determined that it was something related to indexing or caching the game images. images/character_images currently contains upwards of 22,000 individual files, and when those files were temporarily moved there was no delay. I searched the documentation for any references to indexing or caching and experimented with many of the available config options but had no success.

I had the idea of storing all of the LR2 character images inside of an archive that Ren'py wouldn't know how to index. After some trial and error I got this working and succeeded in cutting down load times; Loading time was reduced to a blistering 5 seconds. Unfortunately the overhead required to retrieve the images from the archive introduced a two second lag before each draw statement. This would obviously be highly disruptive to gameplay, so that idea had to be abandoned.

I'm currently working on narrowing down the exact init phase that is taking up all of the startup time with the hope that it will reveal something of use, but I will have to cut my loses soon and turn my attention to other parts of the game. Hopefully giving my brain a rest will help me figure out what to do about this.

Comments

Can you use multiple archives? You should get a log2 relationship with the number of archive files, yes? So there is probably a sweet spot of around 4-16 RPA files where the load time is acceptably short but still gives you the desired improvement.

Dubsington

I'm sorry, but an uncaught exception occurred. While running game code: File "game/script.rpy", line 7314, in script call python: File "game/script.rpy", line 8087, in script call call advance_time from _call_advance_time_1 File "game/script.rpy", line 8509, in script python: File "game/script.rpy", line 8512, in <module> mc.business.run_turn() File "game/script.rpy", line 432, in run_turn self.production_progress(person.focus,person.int,person.production_skill) File "game/script.rpy", line 658, in production_progress serum_count = self.serum_production_array[production_line][2]//the_serum.production_cost #Calculates the number of batches we have made (previously for individual serums, now for entire batches) ZeroDivisionError: integer division or modulo by zero -- Full Traceback ------------------------------------------------------------ Full traceback: File "game/script.rpy", line 7314, in script call python: File "game/script.rpy", line 8087, in script call call advance_time from _call_advance_time_1 File "game/script.rpy", line 8509, in script python: File "C:\Users\User\Desktop\Lab_Rats_2-v0151-pc\Lab_Rats_2-v0.15.1-pc\renpy\ast.py", line 862, in execute renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store) File "C:\Users\User\Desktop\Lab_Rats_2-v0151-pc\Lab_Rats_2-v0.15.1-pc\renpy\python.py", line 1912, in py_exec_bytecode exec bytecode in globals, locals</module>

So I looked into this a bit, and found it's a purely CPU-bound problem. One thread maxing out the core it's scheduled on. On my old 4GHz Sandy Bridge-E, that translates to about 62 seconds to index all the images. Looking at the docs, it looked like Ren'Py will only index "*.jpg" and "*.png" files. So I renamed all the files in character_images to ".img" instead of ".png". Game loads in seconds, so the indexing is gone. The question after that is, will Ren'Py be able to load those images without jumping through hoops? That is, would it load an image based on the file header rather than the extension? I modified script.rpy to reference the new file extension, and fired up a new game. Loading character images definitely works, though there does seem to be a sub-second delay added. Still, better than waiting over a minute for the game to even launch, in my opinion.

Thanny

Thank you for looking into this. Don't let setbacks like this get you down; work at your pace, and the end result will be worth it. :)

Graeme Cracker

There was a game on TF gamesite that had this exact issue. I wanna say ir qas Student Transfer. Maybe poke around their subforum there. The person who fixed it at the time gave an explanation of the fix but I dont remember it.

Troqu

Can you load the images asynchronously?

mazterlith

Why did it take 2s on each draw? Was your logic reloading the necessary assets from your custom archive each time? A better compromise might be to cache each image from your archive the first time you load it. If it's currently loading all of them anyway then you don't even need to worry about freeing up memory.

Apollo

It's good though that you are working on it, because it is a bit silly that it takes 3-4x longer to start than an modern OS to boot

waffel


More Models and Creators