Re: Save in Background
Posted: Sat May 30, 2020 5:31 am
I've been playing with implementing copy-on-write to see how difficult this would be in practice.
The general idea is to install a signal handler and allocate anonymous memory. When it's time to save, mark the memory read-only from the non-save thread, launch save threads, and continue the game as normal. The handler does basic COW behavior: re-map the faulting page to a new read-write "shadow" page and resume execution. This stops the non-save threads from performing any extra saving/non-saving checks which may hamper branch prediction or complicate code. It will however slow down gameplay as pages fault.
Meanwhile, the saving threads map a second view of the anonymous memory at a different base address - this memory is guaranteed immutable, however all pointers will need to be adjusted due to them being at a different base address. The pointer lookups are extra work, and will cause a bad time if something is missed, however it's theoretically isolated to the save code paths only.
When saving is completed, the main thread copies data from the shadow pages back to the original pages, and resets the memory region as read-write.
I've pushed my PoC at https://github.com/tiedotguy/cow if there's any interest.
The general idea is to install a signal handler and allocate anonymous memory. When it's time to save, mark the memory read-only from the non-save thread, launch save threads, and continue the game as normal. The handler does basic COW behavior: re-map the faulting page to a new read-write "shadow" page and resume execution. This stops the non-save threads from performing any extra saving/non-saving checks which may hamper branch prediction or complicate code. It will however slow down gameplay as pages fault.
Meanwhile, the saving threads map a second view of the anonymous memory at a different base address - this memory is guaranteed immutable, however all pointers will need to be adjusted due to them being at a different base address. The pointer lookups are extra work, and will cause a bad time if something is missed, however it's theoretically isolated to the save code paths only.
When saving is completed, the main thread copies data from the shadow pages back to the original pages, and resets the memory region as read-write.
I've pushed my PoC at https://github.com/tiedotguy/cow if there's any interest.