-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Engine-only example crash #6724
Comments
Investigating a bit more, I hope I found the main problem, still testing: In the ammo wasm at With more RTI debugging I figured that the first occurance of And this gave me an idea for a solution which seems to fix this, but I have to test a bit more... basically this contains the problem:
We are Possible solution? Free those vectors later and don't reuse them for each wheel. |
Great investigation! Looks like you are correct. Those vectors are stored as reference, and not get copied to each wheel: |
Nice, thank you for the quick check in actual source! So I guess we could just make an array, add these three vectors for each wheel and just Hmm, edit: Didn't do C++ for a while, but it seems like the vector references are actually copied based on that assignment operator? But once I don't free those vectors after the loop, it works anyway... so IDK why there is a problem here, but the solution somehow speaks for itself that this must be the issue. |
Ah, right, it has the operator overload. Hmm. |
Just printed the vectors: Via: // Add wheels to the vehicle
var wheelAxle = new Ammo.btVector3(-1, 0, 0);
var wheelDirection = new Ammo.btVector3(0, -1, 0);
var connectionPoint = new Ammo.btVector3(0, 0, 0);
console.log('wheelAxle.kB', wheelAxle.kB);
console.log('wheelDirection.kB', wheelDirection.kB);
console.log('connectionPoint.kB', connectionPoint.kB); And then testing the pointers from vehicle, which should be the same pointers, if not copied by value (aka only a pointer/reference copy): And they seem to be all independent... quite a strange mystery 👻 |
Thought the pointer was showing indication that something doesn't get cleaned up, but it was not the case. At least not indicative.
If I hard reset Ammo by forcing it to initialize again, instead of re-using old instance, then the issue goes away. Refreshing browser or hitting reset button give the same result. engine/src/core/wasm-module.js Lines 171 to 183 in 5be4181
static getInstance(moduleName, callback) {
const module = Impl.getModule(moduleName);
// if (module.instance) {
// callback(module.instance);
// } else {
module.callbacks.push(callback);
module.initializing = false;
if (module.config) {
// config has been provided, kick off module initialize
Impl.initialize(moduleName, module);
}
// }
} |
I think the proper fix would be to instantiate a new Ammo instance on reset, as the engine keeps creating new objects in the same Wasm instance, until we eventually run out of memory. I guess something gets referenced to an old object or something. |
Doing a full Ammo instance reset just covers that we have memory leaks that may show up in other scenarios aswell? For example spawning/destroying many cars in a GTA style game. I would like a solution that goes to the root of the problem here 🙈 |
That should be fine. I mean creating multiple cars should be no issue here. I think the problem comes from the fact that when we click reset button, the engine creates a duplicate dynamics world, dispatcher, overlapping pairs cache, etc. without destroying old ones, and something internally gets referred to either duplicate or old system. Clicking reset button would then create yet another set of those. If we don't destroy the old Wasm instance altogether, then we should clear the current instance before creating them again. I think the fact that it doesn't crash if you don't destroy vectors is just a lucky circumstance. |
They are created here: engine/src/framework/components/rigid-body/system.js Lines 381 to 385 in e20814a
And deleted here on refresh: engine/src/framework/components/rigid-body/system.js Lines 1037 to 1055 in e20814a
Since we call engine/examples/iframe/loader.mjs Lines 207 to 214 in e20814a
But memory leaks seem obvious here: engine/src/framework/components/collision/trigger.js Lines 28 to 30 in e20814a
engine/src/framework/components/rigid-body/component.js Lines 179 to 187 in e20814a
engine/src/framework/components/rigid-body/system.js Lines 395 to 396 in e20814a
For starters... at least I don't see any corresponding My gut feeling is we reuse old pointers from e.g. those and that corrupts the memory state - we just have to make sure we free properly what we allocate and the errors should just disappear. |
So I rewrote literally every src/framework/components/ammo.js: const trackedObjects = [];
let createCount = 0;
let deleteCount = 0;
function ammoTrack(object) {
trackedObjects.push(object);
object.deleteCount = 0;
object.stack = new Error().stack; // Track *where* it was created
createCount++;
return object;
}
function ammoPurge() {
for (const o of trackedObjects) {
if (o.deleteCount === 0) {
console.log("Purge", o);
ammoDestroy(o);
}
}
}
function ammoOverview() {
let a = 0;
let b = 0;
for (const o of trackedObjects) {
if (o.deleteCount === 0) {
a++;
} else {
b++;
}
}
console.log(`ammoOverview notDeleted=${a} deleted=${b} createCount=${createCount} deleteCount=${deleteCount}`);
}
function ammoDestroy(o) {
deleteCount++;
o.deleteCount++;
if (o.deleteCount > 1) {
// Should be deleted only once...
debugger;
}
try {
Ammo.destroy(o);
} catch (e) {
console.warn("ammoDestroy> whatever");
}
}
export {ammoTrack, ammoPurge, ammoOverview, ammoDestroy, trackedObjects}; After a refresh I call Clear thing, rigidbody objects aren't freed. Remember that 10x5 wall in the Vehicle example? Those get never freed it seems. Usually I can refresh the example 9x. If I turn the 10x5 wall into a 20x5 wall I can refresh 7x. I counted 64 unfreed objects, but the wall in itself is of course only 50 rigid bodies... but that's a start that should be fixed. Edit: Oops, this kind of measuring didn't account for the |
This is great detective work. I'm guessing the rigid bodies are not destroyed because the hierarchy is never explicitly destroyed? If it was explicitly destroyed, the components wouldn't be removed from all entities, and when a |
Originally reported in #6723
Needs an investigation, if the error is caused by something else.
Repro:
The text was updated successfully, but these errors were encountered: