in0finite / SanAndreasUnity

Open source reimplementation of GTA San Andreas game engine in Unity
https://discord.gg/p6jjud5
MIT License
2.13k stars 352 forks source link

Don't allocate memory inside ArchiveManager.ReadFile(), but instead cache the buffer per thread - can't be done #56

Open in0finite opened 4 years ago

in0finite commented 4 years ago

This turns out not to be that easy. You can't cache the buffer per thread, because the caller may use the returned buffer in different thread.

Even if each thread has it's own buffer, that buffer will be eventually passed to the main thread. The main thread will read from it (eg. to construct a mesh), and in the meantime, the thread which owns that buffer can receive new read request. This read request will result in reading archive file into the buffer, which is being read by the main thread.

Of course, since we know there are at most 2 threads used for reading archive files, we could only use 2 buffers. Actually... we can't. Let's say that main thread generates multiple read requests which read files into the 2nd buffer. The background thread will read one file into this buffer. After that, it will read another file into the same buffer and overwrite contents.

So, the only way to prevent buffer allocation is to have a pool of buffers. When trying to read new file, obtain a buffer from buffer pool. When finished reading a file (and constructing a mesh, for example), return the buffer to the buffer pool. But, this requires changing a lot of code. No need to make sure that buffer is returned in every situation (in case of an error), because GC will collect him.

We would need to limit this pool to, let's say, 10 buffers. This would allow 10 readings without allocating memory. After 10 readings, every new reading will allocate memory.