Optimizing factorio startup performance when running on a hard disk
While my Operating System is installed on a SSD, i install games like Factorio on my HDD. When running on a hard disk, Factorio takes a long time to startup and show the main menu. A significant percentage of that time is spent on IO, reading the game assets from the slow hard disk.
To improve this, we could implement a script that will run at system bootup which will cache all the game assets to RAM. The Factorio game directory is only 4.5 GiB in size and therefore would easily fit in my PC’s 32 GiB RAM.
Results
Before the optimization, the game took 113 seconds to startup1. After the optimization, the game only took 30 seconds. The script takes 230 seconds to run, much higher than the time taken for the game to load probably because the game only loads parts of the files whereas the script always loads the entire file contents into RAM.
Steps
We need to first get the list of all files read by the game at startup. This can be done with the help of inotify. Install the inotify tools packages:
sudo apt install inotify-tools
This package provides the inotifywait
program which can print out the name of file when its accessed by any process in the system. Find out the path to the directory where the game is downloaded and then run the following command.
inotifywait -e access -r -m ~/path-to-game/steamapps/common/Factorio \
--format='%w%f %e' --outfile ~/trace.log
A custom format is set with --format='%w%f %e'
. This is necessary because inotifywait
will print the names of both files and directories and we are only interested in files. The %e
will print ACCESS,ISDIR
for directory and ACCESS
for files. We will later use grep
to remove the directory names from the list.
Run the above command on a terminal and launch the game. Wait for the game to startup and show the main menu and then exit the game and finally terminate the above command with CTRL-C
. The list of files would then be stored in ~/trace.log
This file contains a list of both files and directories. We can filter out directories by running the following:
cat ~/trace.log \
| grep -v 'ACCESS,ISDIR' \
| rev | cut -d ' ' -f 2-| rev > ~/.local/share/preload.list
We first use grep
to remove directory names and then we remove the ACCESS
string from the end using rev
and cut
.
We now have the list of files in preload.list
. what we need to do next is to load the file contents into RAM at system bootup. For this we need a one liner script which needs to be saved to ~/.local/share/preload_factorio.sh
#!/bin/bash
while read i; do cat "$i" > /dev/null;done < ~/.local/share/preload.list
Create a systemd service file in ~/.config/systemd/user/factorio_preload.service
to run this script upon login.
[Unit]
Description=Preload factorio game assets
[Service]
Type=oneshot
ExecStart=/bin/bash %h/.local/share/preload_factorio.sh
IOWeight=1
[Install]
WantedBy=default.target
Activate the above service by running
systemctl --user enable factorio_preload.service
From now on Factorio game assets will be loaded to RAM upon system bootup.
Note: Before you measure the time taken to load the game assets, you need to clear the cache by running:
echo 3 > /proc/sys/vm/drop_caches
-
startup time is measured as the time taken for the game main menu to show up after clicking the launch button on Steam. ↩