From f9208df1db3c03f41763b68ab4fd12b0bb4064ef Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 23 Jul 2023 12:18:03 +0100 Subject: [PATCH] optimised pairs and collisions memory and gc use --- src/collision/Collision.js | 4 ++- src/collision/Detector.js | 22 ++++++++++++++--- src/collision/Pair.js | 16 +++++++++--- src/collision/Pairs.js | 50 +++++++++++++++++++++++--------------- src/core/Engine.js | 2 +- 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 8d21b328..1f24db90 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -152,8 +152,10 @@ var Pair = require('./Pair'); supports[supportCount++] = supportsB[0]; } - // update supports array size + // update supports array size if changed + if (supports.length !== supportCount) { supports.length = supportCount; + } return collision; }; diff --git a/src/collision/Detector.js b/src/collision/Detector.js index a4626e29..c6059b07 100644 --- a/src/collision/Detector.js +++ b/src/collision/Detector.js @@ -22,6 +22,7 @@ var Collision = require('./Collision'); Detector.create = function(options) { var defaults = { bodies: [], + collisions: [], pairs: null }; @@ -45,6 +46,7 @@ var Collision = require('./Collision'); */ Detector.clear = function(detector) { detector.bodies = []; + detector.collisions = []; }; /** @@ -57,12 +59,13 @@ var Collision = require('./Collision'); * @return {collision[]} collisions */ Detector.collisions = function(detector) { - var collisions = [], - pairs = detector.pairs, + var pairs = detector.pairs, bodies = detector.bodies, bodiesLength = bodies.length, canCollide = Detector.canCollide, collides = Collision.collides, + collisions = detector.collisions, + collisionIndex = 0, i, j; @@ -104,7 +107,7 @@ var Collision = require('./Collision'); var collision = collides(bodyA, bodyB, pairs); if (collision) { - collisions.push(collision); + collisions[collisionIndex++] = collision; } } else { var partsAStart = partsALength > 1 ? 1 : 0, @@ -126,7 +129,7 @@ var Collision = require('./Collision'); var collision = collides(partA, partB, pairs); if (collision) { - collisions.push(collision); + collisions[collisionIndex++] = collision; } } } @@ -134,6 +137,10 @@ var Collision = require('./Collision'); } } + if (collisions.length !== collisionIndex) { + collisions.length = collisionIndex; + } + return collisions; }; @@ -180,6 +187,13 @@ var Collision = require('./Collision'); * @default [] */ + /** + * The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector. + * @property collisions + * @type collision[] + * @default [] + */ + /** * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage. * @property pairs diff --git a/src/collision/Pair.js b/src/collision/Pair.js index 8f7ed810..b4ae5bb4 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -74,19 +74,27 @@ var Contact = require('./Contact'); pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; collision.pair = pair; - activeContacts.length = 0; + + var activeContactIndex = 0, + supportsLength = supports.length; - for (var i = 0; i < supports.length; i++) { + for (var i = 0; i < supportsLength; i++) { var support = supports[i], contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index, contact = contacts[contactId]; if (contact) { - activeContacts.push(contact); + activeContacts[activeContactIndex++] = contact; } else { - activeContacts.push(contacts[contactId] = Contact.create(support)); + contact = Contact.create(support); + activeContacts[activeContactIndex++] = contact; + contacts[contactId] = contact; } } + + if (activeContacts.length !== activeContactIndex) { + activeContacts.length = activeContactIndex; + } }; /** diff --git a/src/collision/Pairs.js b/src/collision/Pairs.js index 2c62cd36..bb223b54 100644 --- a/src/collision/Pairs.js +++ b/src/collision/Pairs.js @@ -39,21 +39,19 @@ var Common = require('../core/Common'); Pairs.update = function(pairs, collisions, timestamp) { var pairsList = pairs.list, pairsListLength = pairsList.length, + pairsListIndex = pairsListLength, pairsTable = pairs.table, collisionsLength = collisions.length, collisionStart = pairs.collisionStart, collisionEnd = pairs.collisionEnd, collisionActive = pairs.collisionActive, + collisionStartIndex = 0, + collisionEndIndex = 0, + collisionActiveIndex = 0, collision, - pairIndex, pair, i; - // clear collision state arrays, but maintain old reference - collisionStart.length = 0; - collisionEnd.length = 0; - collisionActive.length = 0; - for (i = 0; i < pairsListLength; i++) { pairsList[i].confirmedActive = false; } @@ -66,10 +64,10 @@ var Common = require('../core/Common'); // pair already exists (but may or may not be active) if (pair.isActive) { // pair exists and is active - collisionActive.push(pair); + collisionActive[collisionActiveIndex++] = pair; } else { // pair exists but was inactive, so a collision has just started again - collisionStart.push(pair); + collisionStart[collisionStartIndex++] = pair; } // update the pair @@ -80,14 +78,14 @@ var Common = require('../core/Common'); pair = Pair.create(collision, timestamp); pairsTable[pair.id] = pair; - // push the new pair - collisionStart.push(pair); - pairsList.push(pair); + // add the new pair + collisionStart[collisionStartIndex++] = pair; + pairsList[pairsListIndex++] = pair; } } // find pairs that are no longer active - var removePairIndex = []; + pairsListIndex = 0; pairsListLength = pairsList.length; for (i = 0; i < pairsListLength; i++) { @@ -95,20 +93,32 @@ var Common = require('../core/Common'); if (!pair.confirmedActive) { Pair.setActive(pair, false, timestamp); - collisionEnd.push(pair); + collisionEnd[collisionEndIndex++] = pair; + // remove inactive pairs if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) { - removePairIndex.push(i); + delete pairsTable[pair.id]; } + } else { + pairsList[pairsListIndex++] = pair; } } - // remove inactive pairs - for (i = 0; i < removePairIndex.length; i++) { - pairIndex = removePairIndex[i] - i; - pair = pairsList[pairIndex]; - pairsList.splice(pairIndex, 1); - delete pairsTable[pair.id]; + // update array lengths if changed + if (pairsList.length !== pairsListIndex) { + pairsList.length = pairsListIndex; + } + + if (collisionStart.length !== collisionStartIndex) { + collisionStart.length = collisionStartIndex; + } + + if (collisionEnd.length !== collisionEndIndex) { + collisionEnd.length = collisionEndIndex; + } + + if (collisionActive.length !== collisionActiveIndex) { + collisionActive.length = collisionActiveIndex; } }; diff --git a/src/core/Engine.js b/src/core/Engine.js index 91b55ac4..cdf03c4a 100644 --- a/src/core/Engine.js +++ b/src/core/Engine.js @@ -60,6 +60,7 @@ var Body = require('../body/Body'); engine.world = options.world || Composite.create({ label: 'World' }); engine.pairs = options.pairs || Pairs.create(); engine.detector = options.detector || Detector.create(); + engine.detector.pairs = engine.pairs; // for temporary back compatibility only engine.grid = { buckets: [] }; @@ -138,7 +139,6 @@ var Body = require('../body/Body'); Constraint.postSolveAll(allBodies); // find all collisions - detector.pairs = engine.pairs; var collisions = Detector.collisions(detector); // update collision pairs