From da99acbf718baa91949bd51345f5f38c3dc92de7 Mon Sep 17 00:00:00 2001 From: liabru Date: Sat, 12 Aug 2023 23:18:15 +0100 Subject: [PATCH 1/5] reduce canvas hit testing in demo when using matter-tools --- demo/src/index.ejs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/demo/src/index.ejs b/demo/src/index.ejs index 45d0cd3..cb568ca 100644 --- a/demo/src/index.ejs +++ b/demo/src/index.ejs @@ -47,6 +47,14 @@ opacity: 0.5; background: transparent !important; } + + @media only screen and (min-width: 1300px) { + /* reduce hit testing when using matter-tools */ + .matter-demo canvas { + position: relative; + z-index: 20; + } + } <% for (var chunk in htmlWebpackPlugin.files.js) { %> From 45cad777f6a08ab62e640aa3ce9e7b895d6d3e45 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 12:17:40 +0100 Subject: [PATCH 2/5] added arrow key navigation of examples in development demo --- demo/src/Demo.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/demo/src/Demo.js b/demo/src/Demo.js index 044a065..39609c4 100644 --- a/demo/src/Demo.js +++ b/demo/src/Demo.js @@ -41,8 +41,10 @@ var demo = function(examples, isDev) { document.title = 'Matter.js Demo' + (isDev ? ' ・ Dev' : ''); if (isDev) { - var buttonSource = demo.dom.buttonSource; - var buttonCompare = buttonSource.cloneNode(true); + // add compare button + var buttonSource = demo.dom.buttonSource, + buttonCompare = buttonSource.cloneNode(true); + buttonCompare.textContent = '⎄'; buttonCompare.title = 'Compare'; buttonCompare.href = '?compare'; @@ -52,11 +54,29 @@ var demo = function(examples, isDev) { window.location = '?compare#' + demo.example.id; event.preventDefault(); }); + buttonSource.parentNode.insertBefore(buttonCompare, buttonSource.nextSibling); + // always show debug info Matter.before('Render.create', function(renderOptions) { renderOptions.options.showDebug = true; }); + + // arrow key navigation of examples + document.addEventListener('keyup', function(event) { + var isBackKey = event.key === 'ArrowLeft' || event.key === 'ArrowUp', + isForwardKey = event.key === 'ArrowRight' || event.key === 'ArrowDown'; + + if (isBackKey || isForwardKey) { + var direction = isBackKey ? -1 : 1, + currentExampleIndex = demo.examples.findIndex(function(example) { + return example.id === demo.example.id; + }), + nextExample = demo.examples[(demo.examples.length + currentExampleIndex + direction) % demo.examples.length]; + + MatterTools.Demo.setExample(demo, nextExample); + } + }); } MatterTools.Demo.start(demo); From 0f0ac9392189b09cd8b86ad41d123036ffbb001f Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 12:56:50 +0100 Subject: [PATCH 3/5] added Example.stress4 --- examples/index.js | 1 + examples/stress4.js | 121 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 examples/stress4.js diff --git a/examples/index.js b/examples/index.js index 940f47b..6e1a615 100644 --- a/examples/index.js +++ b/examples/index.js @@ -40,6 +40,7 @@ module.exports = { stress: require('./stress.js'), stress2: require('./stress2.js'), stress3: require('./stress3.js'), + stress4: require('./stress4.js'), svg: require('./svg.js'), terrain: require('./terrain.js'), timescale: require('./timescale.js'), diff --git a/examples/stress4.js b/examples/stress4.js new file mode 100644 index 0000000..bcbf251 --- /dev/null +++ b/examples/stress4.js @@ -0,0 +1,121 @@ +var Example = Example || {}; + +Example.stress4 = function() { + var Engine = Matter.Engine, + Events = Matter.Events, + Render = Matter.Render, + Runner = Matter.Runner, + Composites = Matter.Composites, + Common = Matter.Common, + MouseConstraint = Matter.MouseConstraint, + Mouse = Matter.Mouse, + Composite = Matter.Composite, + Bodies = Matter.Bodies; + + // create engine + var engine = Engine.create({ + positionIterations: 25, + velocityIterations: 35 + }); + + var world = engine.world; + + // create renderer + var render = Render.create({ + element: document.body, + engine: engine, + options: { + width: 800, + height: 600, + showStats: true, + showPerformance: true + } + }); + + Render.run(render); + + // create runner + var runner = Runner.create({ + isFixed: true + }); + + Runner.run(runner, engine); + + // add bodies + var stack = function(scale, columns, rows) { + return Composites.stack(40, 40, columns, rows, 0, 0, function(x, y) { + var sides = Math.round(Common.random(1, 8)); + + switch (Math.round(Common.random(0, 1))) { + case 0: + if (Common.random() < 0.8) { + return Bodies.rectangle(x, y, Common.random(25, 50) * scale, Common.random(25, 50) * scale); + } else { + return Bodies.rectangle(x, y, Common.random(80, 120) * scale, Common.random(25, 30) * scale); + } + case 1: + return Bodies.polygon(x, y, sides, Common.random(25, 50) * scale); + } + }); + }; + + Composite.add(world, [ + stack(0.2, 61, 15), + stack(0.3, 31, 12), + Bodies.rectangle(400, 0, 800, 50, { isStatic: true, render: { visible: false } }), + Bodies.rectangle(400, 600, 800, 50, { isStatic: true, render: { visible: false } }), + Bodies.rectangle(800, 300, 50, 600, { isStatic: true, render: { visible: false } }), + Bodies.rectangle(0, 300, 50, 600, { isStatic: true, render: { visible: false } }) + ]); + + // scene animation + engine.timing.timeScale = 0.9; + engine.gravity.scale = 0.0007; + + Events.on(engine, 'beforeUpdate', function() { + engine.gravity.x = Math.cos(engine.timing.timestamp * 0.0005); + engine.gravity.y = Math.sin(engine.timing.timestamp * 0.0005); + }); + + // add mouse control + var mouse = Mouse.create(render.canvas), + mouseConstraint = MouseConstraint.create(engine, { + mouse: mouse, + constraint: { + stiffness: 0.2, + render: { + visible: false + } + } + }); + + Composite.add(world, mouseConstraint); + + // keep the mouse in sync with rendering + render.mouse = mouse; + + // fit the render viewport to the scene + Render.lookAt(render, { + min: { x: 0, y: 0 }, + max: { x: 800, y: 600 } + }); + + // context for MatterTools.Demo + return { + engine: engine, + runner: runner, + render: render, + canvas: render.canvas, + stop: function() { + Matter.Render.stop(render); + Matter.Runner.stop(runner); + } + }; +}; + +Example.stress4.title = 'Stress 4'; +Example.stress4.for = '>=0.14.2'; + +if (typeof module !== 'undefined') { + module.exports = Example.stress4; +} From 6142991e0a4fb922c69406d9cec9d5fb8467c49b Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 13:10:09 +0100 Subject: [PATCH 4/5] added repeats and updates options to test tools --- package.json | 4 +-- test/ExampleWorker.js | 73 ++++++++++++++++++++++++------------------- test/Examples.spec.js | 17 +++++++--- test/TestTools.js | 7 ++++- 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index c76bf92..a00d314 100644 --- a/package.json +++ b/package.json @@ -55,11 +55,11 @@ "test-node": "npm run build-dev && node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Examples.spec.js", "test-browser": "node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Browser.spec.js", "test-all": "npm run test-node && npm run test-browser", - "test-save": "SAVE=true npm run test-node", + "test-save": "npm run test-node -- --save=true", "test-watch": "npm run test-node -- --watch", "changelog": "conventional-changelog -i CHANGELOG.md -s -r", "release": "npm version --no-git-tag-version", - "preversion": "git checkout master && npm run lint && SAVE=true npm run test-all", + "preversion": "git checkout master && npm run lint && npm run test-all -- --save=true", "version": "git checkout -b release/$npm_package_version && npm run build" }, "files": [ diff --git a/test/ExampleWorker.js b/test/ExampleWorker.js index 5fe23bb..7cd698a 100644 --- a/test/ExampleWorker.js +++ b/test/ExampleWorker.js @@ -13,50 +13,57 @@ const runExample = options => { frameCallbacks } = prepareEnvironment(options); - const Examples = requireUncached('../examples/index'); - const example = Examples[options.name](); - - const engine = example.engine; - const runner = example.runner; - const render = example.render; - let totalMemory = 0; let totalDuration = 0; let overlapTotal = 0; let overlapCount = 0; let i; - - if (global.gc) { - global.gc(); - } + let j; try { - for (i = 0; i < options.updates; i += 1) { - const time = i * runner.delta; - const callbackCount = frameCallbacks.length; + let runner; + let engine; + let render; - for (let p = 0; p < callbackCount; p += 1) { - totalMemory += process.memoryUsage().heapUsed; - const callback = frameCallbacks.shift(); - const startTime = process.hrtime(); - - callback(time); - - const duration = process.hrtime(startTime); - totalMemory += process.memoryUsage().heapUsed; - totalDuration += duration[0] * 1e9 + duration[1]; + for (i = 0; i < options.repeats; i += 1) { + if (global.gc) { + global.gc(); } - const pairsList = engine.pairs.list; - const pairsListLength = engine.pairs.list.length; + const Examples = requireUncached('../examples/index'); + const example = Examples[options.name](); - for (let p = 0; p < pairsListLength; p += 1) { - const pair = pairsList[p]; - const separation = pair.separation - pair.slop; + runner = example.runner; + engine = example.engine; + render = example.render; + + for (j = 0; j < options.updates; j += 1) { + const time = j * runner.delta; + const callbackCount = frameCallbacks.length; - if (pair.isActive && !pair.isSensor) { - overlapTotal += separation > 0 ? separation : 0; - overlapCount += 1; + for (let p = 0; p < callbackCount; p += 1) { + totalMemory += process.memoryUsage().heapUsed; + const callback = frameCallbacks.shift(); + const startTime = process.hrtime(); + + callback(time); + + const duration = process.hrtime(startTime); + totalMemory += process.memoryUsage().heapUsed; + totalDuration += duration[0] * 1e9 + duration[1]; + } + + const pairsList = engine.pairs.list; + const pairsListLength = engine.pairs.list.length; + + for (let p = 0; p < pairsListLength; p += 1) { + const pair = pairsList[p]; + const separation = pair.separation - pair.slop; + + if (pair.isActive && !pair.isSensor) { + overlapTotal += separation > 0 ? separation : 0; + overlapCount += 1; + } } } } @@ -75,7 +82,7 @@ const runExample = options => { }; } catch (err) { - err.message = `On example '${options.name}' update ${i}:\n\n ${err.message}`; + err.message = `On example '${options.name}' update ${j}:\n\n ${err.message}`; throw err; } }; diff --git a/test/Examples.spec.js b/test/Examples.spec.js index 72899a1..0969e1e 100644 --- a/test/Examples.spec.js +++ b/test/Examples.spec.js @@ -10,7 +10,8 @@ const { comparisonReport, logReport, toMatchExtrinsics, - toMatchIntrinsics + toMatchIntrinsics, + getArg } = require('./TestTools'); const Example = requireUncached('../examples/index'); @@ -18,9 +19,11 @@ const MatterBuild = requireUncached('../build/matter'); const { versionSatisfies } = requireUncached('../src/core/Plugin'); const Worker = require('jest-worker').default; -const specificExamples = process.env.EXAMPLES ? process.env.EXAMPLES.split(' ') : null; -const testComparison = process.env.COMPARE === 'true'; -const saveComparison = process.env.SAVE === 'true'; +const testComparison = getArg('compare', null) === 'true'; +const saveComparison = getArg('save', null) === 'true'; +const specificExamples = getArg('examples', null, (val) => val.split(',')); +const repeats = getArg('repeats', 1, parseFloat); +const updates = getArg('updates', 150, parseFloat); const excludeExamples = ['svg', 'terrain']; const excludeJitter = ['stack', 'circleStack', 'restitution', 'staticFriction', 'friction', 'newtonsCradle', 'catapult']; @@ -42,6 +45,7 @@ const captureExamples = async useDev => { name, useDev, updates: 2, + repeats: 1, stableSort: true, jitter: excludeJitter.includes(name) ? 0 : 1e-10 }))); @@ -50,6 +54,7 @@ const captureExamples = async useDev => { name, useDev, updates: 2, + repeats: 1, stableSort: true, jitter: excludeJitter.includes(name) ? 0 : 1e-10 }))); @@ -58,6 +63,7 @@ const captureExamples = async useDev => { name, useDev, updates: 2, + repeats: 1, stableSort: false, jitter: excludeJitter.includes(name) ? 0 : 1e-10 }))); @@ -72,7 +78,8 @@ const captureExamples = async useDev => { const completeRuns = await Promise.all(examples.map(name => singleThreadWorker.runExample({ name, useDev, - updates: 150, + updates: updates, + repeats: repeats, stableSort: false, jitter: excludeJitter.includes(name) ? 0 : 1e-10 }))); diff --git a/test/TestTools.js b/test/TestTools.js index 86c4485..70b4335 100644 --- a/test/TestTools.js +++ b/test/TestTools.js @@ -254,6 +254,11 @@ const requireUncached = path => { return module; }; +const getArg = (name, defaultValue=null, parser=(v) => v) => { + const value = process.argv.find(arg => arg.startsWith(`--${name}=`)); + return value ? parser(value.split('=')[1]) : defaultValue; +}; + const toMatchExtrinsics = { toMatchExtrinsics(received, value) { const similaritys = extrinsicSimilarity(received, value, 'extrinsic'); @@ -286,6 +291,6 @@ const toMatchIntrinsics = { }; module.exports = { - requireUncached, comparisonReport, logReport, + requireUncached, comparisonReport, logReport, getArg, serialize, toMatchExtrinsics, toMatchIntrinsics }; \ No newline at end of file From e668c028a061e5c9fd351c51c49346a3234192b8 Mon Sep 17 00:00:00 2001 From: liabru Date: Sun, 13 Aug 2023 13:15:29 +0100 Subject: [PATCH 5/5] updated benchmark tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a00d314..d84dffb 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "lint": "eslint 'src/**/*.js' 'demo/src/**/*.js' 'examples/*.js' 'webpack.*.js'", "doc": "yuidoc --config yuidoc.json --project-version $npm_package_version", "doc-watch": "nodemon --delay 3 --watch 'matter-doc-theme' --watch src -e 'js,html,css,handlebars' --exec 'npm run doc'", - "benchmark": "EXAMPLES=stress3 npm run test-node", + "benchmark": "npm run test-node -- --examples=stress3,stress4 --updates=300 --repeats=3", "test": "npm run test-node", "test-node": "npm run build-dev && node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Examples.spec.js", "test-browser": "node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Browser.spec.js",