Re: Use fork() on *nix systems for doing save game
Posted: Sun Jul 30, 2017 3:27 am
fork sounds like a good idea on the surface... but then it marks ALL pages in source and destination as copy on write, so as the game continues to run and update the state in memory, all of those pages have to get a new map and get a copy. It's not just the child process that copies on write, otherwise it would get a invalid page.
Synchronizing it such that nothing is happening ( nothing in any lua scripts doing anything at the time I would think would be more tricky.
Even if the child process is mostly a read only process, once it exits, all of the pages in the parent are still marked copy on write. (except those that the parent updated while updating the game state) you'd get a significant stutter in the parent process after the fork.
whether sounds are playing or not is really irrelavent to the child and none of the threads should really have to be forked... from its own entry point it could just start scanning memory and building an image to save... probably internaly there is a point like beginning to render the display where things have completed and would be a good time to fork for consistent game-state data.
---
slowness is probably due to 'good coding practices' that associate serialization methods with their classes; this would cause lots of calls that move tiny tiny bits instead of having a separate state loop that can just iterate through the data without calls. A call is much likely to be a cpu cache hit than a jump in a loop; though even jumps cause pipeline flushses.
maybe once it's closer to 1.0 things can be migrated to more of a dedicated serialize-everything sort of routine instead of billions of tiny calls.
My own image library started as something resembling allegro too; one of the first things I did was to replace 'target any pixel type' to 'everything internally is 32 bit pixels' and then instead of calling 'compute pixel' for every operation, moved to for( y) for( x ) (*output++) = (*input++) (to even remove the computed index into the arrays, or even simple offset index into arrays) to copy an image for instance... a minor varation to test if( input alpha is 255 copy, else do a computation for alpha) instead of calling a routine to compute the alpha increased performance immensely. Hooray for #define.
Synchronizing it such that nothing is happening ( nothing in any lua scripts doing anything at the time I would think would be more tricky.
Even if the child process is mostly a read only process, once it exits, all of the pages in the parent are still marked copy on write. (except those that the parent updated while updating the game state) you'd get a significant stutter in the parent process after the fork.
whether sounds are playing or not is really irrelavent to the child and none of the threads should really have to be forked... from its own entry point it could just start scanning memory and building an image to save... probably internaly there is a point like beginning to render the display where things have completed and would be a good time to fork for consistent game-state data.
---
slowness is probably due to 'good coding practices' that associate serialization methods with their classes; this would cause lots of calls that move tiny tiny bits instead of having a separate state loop that can just iterate through the data without calls. A call is much likely to be a cpu cache hit than a jump in a loop; though even jumps cause pipeline flushses.
maybe once it's closer to 1.0 things can be migrated to more of a dedicated serialize-everything sort of routine instead of billions of tiny calls.
My own image library started as something resembling allegro too; one of the first things I did was to replace 'target any pixel type' to 'everything internally is 32 bit pixels' and then instead of calling 'compute pixel' for every operation, moved to for( y) for( x ) (*output++) = (*input++) (to even remove the computed index into the arrays, or even simple offset index into arrays) to copy an image for instance... a minor varation to test if( input alpha is 255 copy, else do a computation for alpha) instead of calling a routine to compute the alpha increased performance immensely. Hooray for #define.