diff --git a/src/framework/core/js/DataBinding.js b/src/framework/core/js/DataBinding.js index b296633e21..81d5029d33 100644 --- a/src/framework/core/js/DataBinding.js +++ b/src/framework/core/js/DataBinding.js @@ -840,6 +840,8 @@ fluid.relayRecursionBailout = 100; // is transactional but it does not require the transaction to conclude in order to fire - it may be reused as many times as // required within the "overall" transaction whilst genuine (external) changes continue to arrive. +fluid.count = 0; + // TODO: Vast overcomplication and generation of closure garbage. SURELY we should be able to convert this into an externalised, arg-ist form /** Registers a listener operating one leg of a model relay relation, connecting the source and target. Called once or twice from `fluid.connectModelRelay` - * see the comment there for the three cases involved. Note that in its case iii)B) the applier to bind to is not the one attached to `target` but is instead @@ -882,6 +884,9 @@ fluid.registerDirectChangeRelay = function (target, targetSegs, source, sourceSe } var transEl = transRec[applierId]; transRec[linkId] = transRec[linkId] || 0; + ++fluid.count; + //fluid.log("SourceListener " + fluid.count + " firing with value " + JSON.stringify(newValue, null, 2) + " from source ", source, " to target ", target, + // " sourceSegs ", sourceSegs, " targetSegs ", targetSegs); // Crude "oscillation prevention" system limits each link to maximum of 2 operations per cycle (presumably in opposite directions) var relay = true; // TODO: See FLUID-5303 - we currently disable this check entirely to solve FLUID-5293 - perhaps we might remove link counts entirely if (relay) { diff --git a/tests/framework-tests/core/js/DataBindingTests.js b/tests/framework-tests/core/js/DataBindingTests.js index fac1966b02..0d16f54d72 100644 --- a/tests/framework-tests/core/js/DataBindingTests.js +++ b/tests/framework-tests/core/js/DataBindingTests.js @@ -1441,6 +1441,89 @@ jqUnit.test("FLUID-6390 V: Updating lensed components as an array", function () fluid.tests.fluid6390assertModelValues("Updated model values are correct", that, []); }); +/** FLUID-6395 - Performance in fan-out of relays **/ + +fluid.tests.fluid6395generate = function (fanOut) { + return fluid.generate(fanOut, function (index) { + return { + value: index + }; + }, true); +}; + +fluid.defaults("fluid.tests.fluid6395root", { + gradeNames: "fluid.modelComponent", + fanOut: 200, + model: { + modelSource: "@expand:fluid.tests.fluid6395generate({that}.options.fanOut)" + }, + dynamicComponents: { + child: { + sources: "{that}.model.modelSource", + type: "fluid.modelComponent", + options: { + model: { + value: "{source}.value" + } + } + } + } +}); + +jqUnit.test("FLUID-6395: Performance of relay rules with increasing fan-out - fine-grained sharing", function () { + var that = fluid.tests.fluid6395root(); + var children = fluid.queryIoCSelector(that, "fluid.modelComponent"); + jqUnit.assertEquals("Constructed " + that.options.fanOut + " children: ", that.options.fanOut, children.length); + var now = Date.now(); + children[0].applier.change("value", 999); + var elapsed = Date.now() - now; + jqUnit.assertEquals("Change relayed to parent model ", 999, that.model.modelSource[0].value); + fluid.log("Applied change in " + elapsed + "ms"); +}); + +fluid.defaults("fluid.tests.fluid6395root2", { + gradeNames: "fluid.modelComponent", + fanOut: 100, + source: "@expand:fluid.tests.fluid6395generate({that}.options.fanOut)", + model: { + focus: {row: 0, col: 0} + }, + components: { + midChild: { + type: "fluid.modelComponent", + options: { + model: { + focus: "{fluid6395root2}.model.focus" + } + } + } + }, + dynamicComponents: { + child: { + sources: "{that}.options.source", + type: "fluid.modelComponent", + options: { + model: { + focus: "{midChild}.model.focus" + } + } + } + } +}); + +jqUnit.test("FLUID-6395 II: Performance of relay rules with increasing fan-out - coarse-grained sharing", function () { + var that = fluid.tests.fluid6395root2(); + var children = fluid.queryIoCSelector(that, "fluid.modelComponent"); + jqUnit.assertEquals("Constructed " + that.options.fanOut + " children: ", that.options.fanOut + 1, children.length); + var now = Date.now(); + children[1].applier.change("focus", {row: 7, col: 5}); + fluid.count = 0; + // that.applier.change("someValue", 999); + var elapsed = Date.now() - now; + jqUnit.assertEquals("Change relayed to parent model ", 7, that.model.focus.row); + fluid.log("Applied change in " + elapsed + "ms"); +}); + /** FLUID-6570: Short-form free transforms **/ fluid.defaults("fluid.tests.fluid6570root", {