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
  1. startup time is measured as the time taken for the game main menu to show up after clicking the launch button on Steam.