Skip to content

Instantly share code, notes, and snippets.

@WarpspeedSCP
Last active August 26, 2019 19:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WarpspeedSCP/cfa11e44f91c9b157a52c25f601171df to your computer and use it in GitHub Desktop.
Save WarpspeedSCP/cfa11e44f91c9b157a52c25f601171df to your computer and use it in GitHub Desktop.
GSoC 2019 end report

Motivation

The goal of my project was to replace the already existing FileAccessBuffered class with a more flexible and robust solution for caching IO without relying on the OS, on any platform including desktop and consoles.

The old solution to the problem of cached IO was to use FileAccessBuffered. This was a problem because FileAccessBuffered only supported reading ahead and did not allow for seeking.

Current State

The solution I have developed is to provide a separate "cache server" module to allow for caching within the engine. This module's functionality is focussed around two classes: FileAccessCached and FileCacheManager. FileCacheManager is a custom server class that performs the caching and manages all the cached files. It acts as a middleman between the engine and the OS.

FileAccessCached is the interface through which the engine interacts with FileCacheManager. It provides an interface similar to the built in FileAccess API and supports all operations that can be performed on a normal FileAccess.

Though FileCacheManager has only one front end, it is possible to use any class that inherits from FileAccess as the backing interface. Ideally, the user would want to use an unbuffered interface on the backend (like the FileAccessUnbufferedUnix class I've included in the module as an example). It should even be possible to use classes such as FileAccessNetwork with this module.

Currently, there is no way to select the backing file interface in FileCacheManager, but I will include a way to do that soon. I also need to finish the implementation of FileAccessWindows, and there's still at least one bug left to solve.

This project is by no means complete, but it's getting there. I'll continue working on it to get it in a better state.

If you'd like a clearer picture of how the module works, I suggest you look in the repo.

There's also a test repo I made to sort of stress-test the module.

  • Beware, the code in the repo is not currently in a ready state ,and it will spew a ton of log messages at you if you try it out.

A Brief History

This project had quite a bumpy beginning. While the design I'd envisioned used a technique known as paging to provide the caching behaviour, what I started out with was quite off the mark; it was more akin to memory management than paging. Punto caught me out on this when I talked to him about it, and from there, I got started with the module in earnest.

A similar thing happened later on as well when I tried to make a very convoluted system to handle the problem of keeping files cached even if the backing source was closed.

Throughout June, the basic framework of the module was established. In July, I focussed on gettinng the kinks out the design and making incremental improvements. Sadly, I didn't really follow any testing methodology while developing this module, which is something I regret now. I spent most of August weeding out bugs. It was a mostly successful endeavour.

Bugs

Speaking of bugs, the one major bug that's blocking me right now has to do with the read operation.

FileCacheManager internally uses a Multiple-Producer Single-Consumer (MPSC) queue to atomically send messages for reads and writes to the IO thread from other threads.

In certain cases, successive read operations which are pushed onto the queue seem to overwrite each other.

For example, this means that enqueueing three separate operations results in all but the last operation from actually being enqueued.

What I've Learnt

Designing a system is hard. But it's pretty fun too.

Make any system multithreaded and its complexity immediately skyrockets.

Always remember to run your code through the debugger once, without breakpoints. It helps a lot when looking for (non)obvious runtime errors.

It's ok not to be perfect. It all comes in due course.

Don't overthink things. It's not worth the effort.

Acknowledgements

I'm really grateful to my mentor punto for his help. He always has great advice for me, and he's a really chill guy. Actually, that could apply to the entire Godot engine community too. You're all awesome, guys.

I'd also like to thank all the other GSoC students who completed their journey with me. It was a fun ride. 11/10, would do it again.

I couldn't thank my parents and my friends enough for the encouragement and support they've given me. I wouldn't have thought of participating in GSoC if it weren't for them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment