Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STL, OOM, and exceptions #127

Closed
sherief opened this issue Apr 11, 2022 · 5 comments
Closed

STL, OOM, and exceptions #127

sherief opened this issue Apr 11, 2022 · 5 comments

Comments

@sherief
Copy link
Contributor

sherief commented Apr 11, 2022

The readme mentions two seemingly-contradictory points about Jolt:

  • It uses C++17 and only depends on the standard template library.
    -It doesn't make use of compiler generated RTTI or exceptions.

STL containers expect allocaters, even the STLAlignedAllocator provided, to throw an exception on Out Of Memory (OOM) and never to return NULL. I have ran into an OOM situation and it was Not Pretty.

I don't see a path towards fixing this without getting rid of STL containers, is this something there's interest in mainlining?

@jrouwe
Copy link
Owner

jrouwe commented Apr 11, 2022

Jolt does not handle OOM situations. In my opinion, for games, it is pointless to try to handle this gracefully. If you're in the middle of a complex job graph and then one of the jobs fails to allocate memory, you'll have to somehow clean up all temporaries while leaving everything in a sensible state. This makes the code very complex and is incredibly hard to test.

And the question is: What are you going to do when you go OOM? In the best case, I think, you can show a dialog box to the user that the game ran out of memory and then abort. I'm planning to support a custom memory allocator at some point in the future, and in case of OOM I expect that function to just not return (show dialog, maybe save some data + exit application).

@sherief
Copy link
Contributor Author

sherief commented Apr 11, 2022

Saving some data then exiting on OOM is critical to avoid data loss during content creation, as this runs in the editor for my use case. I don't mind libraries throwing their hands in the air and saying "I'm done, you're OOM!" and leaving the caller to handle things - you can't really expect more from them as supporting infra.

However, the current state of affairs is "you make this call into physics, and the entire process might come down crashing. Good luck!". For a game with pre-designed assets and limited to no user-generated content this is fine, but outside of these domains it's an issue.

The bar for me is "it's fine if you fail or corrupt your own state on OOM, but leave the rest of the process alone".

@jrouwe
Copy link
Owner

jrouwe commented Apr 12, 2022

So the current state of things is:

  • If you try to create too many bodies / characters it will return a nullptr (although there is a small dynamic allocation there too).
  • In PhysicsSystem::Update you pass in a temporary allocator. The amount of memory it allocates will more or less be the same every frame and depends on the max amount of bodies, contact constraints and body pairs you specified in the PhysicsSystem::Init call and the max in flight body pairs you specified in PhysicsSystemSettings. There's 1 allocation left in the update that should go to the temp allocator as well (but is difficult to get there) and that should be it memory allocation wise. If you have provided a temp allocator large enough for those parameters, you should never crash with OOM. Stuff will fall through the world if you run out of contact constraints / body pairs.
  • The dynamic memory allocations are all happening when you create bodies / shapes / constraints etc. The allocations there are all pretty small. The only larger allocations would come from MeshShape and HeightFieldShape. As long as you don't call the functions when you're really low on memory you should be fine.

You could potentially compile Jolt with exceptions on and then catch the exceptions from the calling code, but I have never tried this.

@jrouwe
Copy link
Owner

jrouwe commented Apr 13, 2022

B.t.w. to answer your original question: I've considered many times to write my own STL inplementations, but so far they have never gotten in the way of performance so I haven't done it. I think the most interesting candidate for replacement is the vector class, the other STL classes (like string, unordered_map, deque) are not used that often. Classes like atomic, thread, fstream I would like to use from STL simply because it would drag in too much platform dependent code. So a vector class (if it doesn't depend on anything external) would be interesting for mainlining.

The first thing that needs to be done I think is to define a good interface for an external allocator and hook it up to the STL implementation. I haven't quite settled on what it should look like. I think there needs to be a separate one for 'resources' (like shapes), one for 'run-time instances' (like bodies) and one for temporary allocations (which could come in two flavors, a stack based allocator like the current TempAllocator and one that is more suitable for random allocations/frees). I would like for example for shapes to be allocated as 1 contiguous memory block, but haven't worked out yet how that should work with reference counting.

@jrouwe
Copy link
Owner

jrouwe commented Apr 21, 2022

Closing this one as it is a duplicate of #55

@jrouwe jrouwe closed this as completed Apr 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants