-
Notifications
You must be signed in to change notification settings - Fork 224
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
Clear external tileset skeletons from tile tree to save memory usage #1107
base: main
Are you sure you want to change the base?
Conversation
…external-tilesets-2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @azrogers, this is so good! I tried flying around with Google Photorealistic 3D Tiles in Cesium for Unreal, and memory usage stays extremely steady. Previously I believe it would have gone up quite quickly. I didn't see any crashes or other dodgy behavior either. This will be a major improvement for our users!
Mostly small comments here, but I did notice a couple of cases where I think there's potential for (rare) bad behavior.
I think it's also worth taking a bit of time to think through whether there could be any other gotchas like this, and generally do everything we can to thoroughly test everything. Perhaps bring back the soak test from #1415?
…external-tilesets-2
…um-native into unload-external-tilesets-2
@kring Looks like reversing the direction of iteration, as well as unloading empty tiles, worked great! I'll take a look at that soak test and think of some other ways we could verify correct behavior here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more small things here. Also please update CHANGES.md.
Bringing the soak test up-to-date (now in CesiumGS/cesium-unreal#1615 for reasons detailed in that PR) did identify some crashes, including issues with |
I realize now that |
It's now tracking most of the tile pointer usages in |
Almost fixed all the issues. First up, the fix for the issue where external tilesets would sometimes be unloaded while some of their children were setTileContent(tile, std::move(pair.result), pair.pRenderResources);
tile.decrementDoNotUnloadCount("TilesetContentManager::loadTileContent done loading"); The issue with these two lines is that, despite the The other fix at least makes sense. Turns out, while The easiest solution is just to make sure we're unloading the entirety of bool Tileset::_clearChildrenRecursively(Tile* pTile) noexcept {
// Iterate through all children, calling this method recursively unless the
// child is still in _loadedTiles. If the child is still in _loadedTiles, or
// any of its children (or children's children and so on) are in _loadedTiles,
// we return false so we don't clear the children prematurely.
for (Tile& child : pTile->getChildren()) {
if (this->_loadedTiles.contains(child) ||
!_clearChildrenRecursively(&child)) {
return false;
}
}
pTile->clearChildren();
return true;
} That way, if there are children that still haven't been unloaded, we will hold off on clearing the children. And if this method returns The remaining issue is a result of this fix - because the external tileset |
On the first ordering issue: you can test this out by checking out 140a7d9 and adding log statements to both |
Do you have an insight into why this matters? Only the main thread should ever look at the If any of those assumptions are violated (i.e., if any Tile property is read or written off the main thread), then that's the real problem. We do, in some cases, create |
Closes #739. Currently, though the content of tiles are unloaded when no longer used, the "skeletons" - the
Tile
objects - created by loading external tilesets are never unloaded. This can cause memory usage to steadily increase. This change implements a_doNotUnloadCount
number on each tile that tracks situations where the tile's pointers are still in use. When a tile is in a situation where its pointer is being used - the tile is being loaded, for example - it increments this count on the tile and each of its parent tiles, and when the pointer is no longer needed, this counter is decremented up the tree as well. This means we can clear the children of external tilesets when their_doNotUnloadCount
number is 0. This implementation also includes aTileDoNotUnloadCountTracker
class, enabled with theCESIUM_DEBUG_TILE_UNLOADING
switch, that tracks the source of every modification to a tile's_doNotUnloadCount
.