# Reducing load times

This topic is 4098 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

##### Share on other sites
You won't find a whole lot on this topic, because most of it is beyond your control at the OS and hardware levels. As long as your data files are in a sane format and can be easily/sequentially read, there isn't much you can do. You want your data in as close to the engine's run-time format, if not exactly, as possible while maintaining easy edit ability. Having to do a lot of text parsing and conversion of data on the CPU can add up to a good bit of time as well.

Compression can speed things up, but depending on the type of compression and how you time/synch everything up, it could be slower. Using container files can help with speed as well, since they are seen by the OS as a single file, which is then cached sequentially as you're reading it. If you place your files in the container sequentially and the file is not too fragmented on the disk, your pull from disk time can drop a little.

Something to also consider, as you mentioned a threaded approach, is to asynchronously load your data. In places where you can, load your data bit by bit in the background before it is needed. You won't get anything amazing as far as speed, but the effect of remaining interactive while loading what you need is better than a slightly reduced load time where everything stops. You should be able to find a bit on this topic, as it's becoming quite popular, especially in console games.

##### Share on other sites
The multithreaded method is a real dead end since the loading thread will be doing nothing 99% of the time whilst the decompressing thread will be doing nothing 1% of the time. The best solution is to use asynchronous disk IO if it's available. It works like this:
1. Load first chunk of data, n=12. Start asynchronous load of chunk n+1 of data3. Decompress chunk n of data4. Wait for chunk n+1 of data to finish loading5. ++n6. Goto 2

The above is only efficient for large n, there's little to gain for small n - you will need to profile the loading times to determine if there's an improvement.

Of course, the load times do depend on where the data is coming from and how it's stored. The overhead for file access is in descending order: opening files, seeking, reading. Things get much worse when reading from CD/DVD - opening files and seeking are phenomenonly slow, reading is OK provided is a big sequential read. So, on CD/DVD, having lots of files is really bad, having a packed file that requires seeking is not quite as bad.

Given the above, I have developed a system that can really speed up CD/DVD load times at the cost of slightly larger data files. I have used this to speed up a PS2 load time from minutes to seconds.

The method I developed required three versions of a file IO class. All file IO was done using the class:
class FileIO{public:  static FileIO *Open (char *filename);  void Close ();  void Seek (int position, int origin);  void Read (void *dest, int num_bytes);  static void BeginFastRead (char *filename);  static void EndFastRead ();};

The first version just mapped the first four functions to the OS file routines and the last two were empty. The second version again mapped the first four functions to the OS routines, but this time the read function also wrote the data that was read to an output file as specified by the BeginFastRead function. The final and production version had empty functions for the first three methods and the Read function read from the file specified in the call to BeginFastRead. This leads to fast CD/DVD speeds as the data is stored on the disk in a way the disk can get it really quickly, i.e. one seek and one long sequential read.

An example:
void LoadLevel (char *levelname){  FileIO::BeginFastRead (levelname + ".fast");  FileIO *level_file = FileIO::Open (levelname);  ReadLevel (level_file);  level_file->Close ();  for each (Texture in level data)  {    FileIO *texture_file = FileIO::Open (texture_name);    ReadTexture (texture_file);    texture_file->Close ();  }  for each (StaticObject in level data)  {    FileIO *object_file = FileIO::Open (object_name);    ReadTexture (object_file);    object_file->Close ();  }  // load other stuff  FileIO::EndFastRead ();}

Skizz

##### Share on other sites
Quote:
 Original post by Skizz1. Load first chunk of data, n=12. Start asynchronous load of chunk n+1 of data3. Decompress chunk n of data4. Wait for chunk n+1 of data to finish loading5. ++n6. Goto 2The above is only efficient for large n, there's little to gain for small n - you will need to profile the loading times to determine if there's an improvement.

Yeah, that seems more reasonable than dedicated threads. The CPU manipulation will probably be done way before the next data chunk is in memory. I'll keep it under my hat ;)

Quote:
 The first version just mapped the first four functions to the OS file routines and the last two were empty. The second version again mapped the first four functions to the OS routines, but this time the read function also wrote the data that was read to an output file as specified by the BeginFastRead function. The final and production version had empty functions for the first three methods and the Read function read from the file specified in the call to BeginFastRead. This leads to fast CD/DVD speeds as the data is stored on the disk in a way the disk can get it really quickly, i.e. one seek and one long sequential read.

I'm not entirely understanding this. The second version wrote a new file? You mean like it wrote a whole level's worth of data to a single file for later opening as a pre-computation step?

-----------------------------------------
I've played with noise a little before. It seems to me that for textures, which seem to take the most disk space and time to load, you could use noise to "up" the resolution for some textures. Maybe save your brick texture or floor textures as 256x256 and then apply a simple noise to make them work as 512x512 or 1024x1024. For textures details that are inherantly static anyway, like dimples in a brick, this might give pretty good results with appreciable cutdown bulk.

This would also let you shift the resolution up for other textures (if the hardware allowed it). Make the decals that contain text on the walls of the spaceship readable.

The extreme of this, all procedural, doesn't seem to be any faster from what I've seen in the demo scene. I might try a hybrid approach out at some point and see how well it works.

##### Share on other sites
the games are a bit old but some of the concepts are interesting.

http://www.drizzle.com/~scottb/gdc/

It discusses the way dungeon siege was made to have no loading screens. Discusses the implications of this from file format and using memory mapped reads all the way up to game implications, viewpoint restrictions and teleportation timing.

##### Share on other sites
Quote:
 Original post by DaishimYou won't find a whole lot on this topic, because most of it is beyond your control at the OS and hardware levels.

Considering that it's one of the more popular complaints gamers have about pretty much any game, I think it's weird that there isn't more attention paid to it.

If the assets you need to load are fixed, then yeah, you don't have alot of control. However, take the case with something like Civ3 or 4. If I'm playing and save the game, lose a battle, and reload, the game spends alot of time loading things back from disk. Orders of magnitude longer than it took to save. Some games are really quite good with load times, and others aren't.

If you designed your engine (not sure how it would work, but bear with me) around the idea that most of the time the assets you need are already somewhere in memory, you might be able to drastically reduce load times from dying or reloading. You'd need a way to 'tag' each asset in memory and from disk with a hash. When you want to load an asset from disk, maybe check what you already have in memory for the hash.

Of course, if most of your assets don't exist in any form outside of the video card, this might not be practical.

##### Share on other sites
Quote:
 Original post by Satookthe games are a bit old but some of the concepts are interesting.http://www.drizzle.com/~scottb/gdc/It discusses the way dungeon siege was made to have no loading screens. Discusses the implications of this from file format and using memory mapped reads all the way up to game implications, viewpoint restrictions and teleportation timing.

Excellent link, thanks. I'm reading it over now

##### Share on other sites
Quote:
 Original post by NumsgilI'm not entirely understanding this. The second version wrote a new file? You mean like it wrote a whole level's worth of data to a single file for later opening as a pre-computation step?

Yes, it does indeed write a new file. The second version effectively compiles the level data from multiple randomly accessed files into a single sequential file. The third version doesn't require any of the source files, just the file created by step 2.

The sharp eyed amongst you will see the downsides to this system.

Skizz

##### Share on other sites
Quote:
 Original post by NumsgilHowever, take the case with something like Civ3 or 4. If I'm playing and save the game, lose a battle, and reload, the game spends alot of time loading things back from disk. Orders of magnitude longer than it took to save.
I'm not sure if this is the case in Civ3, but lots of games [and apps in general, for that matter] save progress or files by taking an in-game snapshot of the current progress, and shipping off the actual save process to another thread that just does it all in the background. This means that the "save time" that the user experiences is often times only the time required to take a snap-shot of what is going on at the time, and create a thread to actually do all the data-saving [you aren't actually waiting for the possible compression steps, all the expensive computations, or the actual disk writes]. This means saves can occur over longer periods of time, and only have to stall the action long enough to gather up the data.

Worked pretty well for me, cut my load times down lots, and allowed me to just flag files for opening, and go back to my game while they load in the background.

##### Share on other sites
Quote:
Original post by Numsgil
Quote:
 Original post by DaishimYou won't find a whole lot on this topic, because most of it is beyond your control at the OS and hardware levels.

Considering that it's one of the more popular complaints gamers have about pretty much any game, I think it's weird that there isn't more attention paid to it.

It's because load time is considered to be the point where performance doesn't really matter. If something can be done at load time instead of in-game, it's moved out to load time. Optimisation of gameplay performance usually takes precedence over load-time performance.

1. 1
2. 2
Rutin
20
3. 3
khawk
16
4. 4
A4L
14
5. 5

• 11
• 16
• 26
• 10
• 11
• ### Forum Statistics

• Total Topics
633756
• Total Posts
3013707
×