Skip to content

Commit

Permalink
perf: advanced compiler optimizations for special directives
Browse files Browse the repository at this point in the history
- special directives *do not* deoptimize by default
  - it is up to the special directive to decide
  - this is made possible by the hydration engine, which handles the initial render regardless of optimization
  - `compileTemplateExpression` returns a boolean showing if the template was static or dynamic
  - deoptimization is only done if the element must be diffed every time (m-if, m-for, m-model)
- m-if, m-for, and m-model deoptimize
- m-on deoptimizes only if dynamic parameters are involved
- m-literal only deoptimizes if a dynamic property is being set
- add dbmon repaint rate
  • Loading branch information
kbrsh committed Sep 2, 2017
1 parent f3fa265 commit 3fc782c
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 70 deletions.
42 changes: 42 additions & 0 deletions benchmarks/dbmon/lib/monitor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
var RenderRate = function() {
var container = document.createElement( 'div' );
container.id = 'stats';
container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:110px;bottom:0px;';

var msDiv = document.createElement( 'div' );
msDiv.id = 'ms';
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
container.appendChild( msDiv );

var msText = document.createElement( 'div' );
msText.id = 'msText';
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
msText.innerHTML= 'Repaint rate: 0/sec';
msDiv.appendChild( msText );

var bucketSize = 20;
var bucket = [];
var lastTime = Date.now();
return {
domElement: container,
ping: function () {
var start = lastTime;
var stop = Date.now();
var rate = 1000 / (stop - start);
bucket.push(rate);
if (bucket.length > bucketSize) {
bucket.shift();
}
var sum = 0;
for (var i = 0; i < bucket.length; i++) {
sum = sum + bucket[i];
}
msText.textContent = "Repaint rate: " + (sum / bucket.length).toFixed(2) + "/sec";
lastTime = stop;
}
}
};

var renderRate = RenderRate();
document.body.appendChild(renderRate.domElement);

(function (exports) {
'use strict';

Expand Down
15 changes: 8 additions & 7 deletions benchmarks/dbmon/scripts.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
var app = new Moon({
root: '#app',
root: "#app",
data: {
databases: []
}
});

perfMonitor.startFPSMonitor()
perfMonitor.startMemMonitor()
perfMonitor.initProfiler("render")
perfMonitor.startFPSMonitor();
perfMonitor.startMemMonitor();
perfMonitor.initProfiler("render");

function run() {
app.set('databases', ENV.generateData().toArray());
perfMonitor.startProfile("render")
app.set("databases", ENV.generateData().toArray());
perfMonitor.startProfile("render");
Moon.nextTick(function() {
perfMonitor.endProfile("render")
perfMonitor.endProfile("render");
renderRate.ping();
});
setTimeout(run, ENV.timeout);
}
Expand Down
32 changes: 20 additions & 12 deletions dist/moon.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,15 +966,19 @@
}

var compileTemplateExpression = function(expression, exclude, dependencies) {
var dynamic = false;
var references;
while((references = expressionRE.exec(expression)) !== null) {
var reference = references[1];
if(reference !== undefined && dependencies.indexOf(reference) === -1 && exclude.indexOf(reference) === -1) {
dependencies.push(reference);
if(reference !== undefined && dependencies.indexOf(reference) === -1) {
if(exclude.indexOf(reference) === -1) {
dependencies.push(reference);
}
dynamic = true;
}
}

return dependencies;
return dynamic;
}

var scanTemplateStateUntil = function(state, re) {
Expand Down Expand Up @@ -1405,8 +1409,6 @@
propsCode += generated;
}
}

dynamic = true;
} else if(name$1[0] === "m" && name$1[1] === "-") {
hasDirectives = true;
dynamic = true;
Expand Down Expand Up @@ -2149,6 +2151,8 @@
break;
}
}

node.meta.shouldRender = 1;
},
afterGenerate: function(prop, code, node, parentNode, state) {
var value = prop.value;
Expand All @@ -2169,10 +2173,6 @@
}
};

specialDirectives["m-else"] = {

};

specialDirectives["m-for"] = {
beforeGenerate: function(prop, node, parentNode, state) {
// Setup Deep Flag to Flatten Array
Expand All @@ -2189,7 +2189,9 @@
var exclude = state.exclude;
prop.data.forInfo = [iteratable, aliases, exclude];
state.exclude = exclude.concat(aliases.split(","));
compileTemplateExpression(iteratable, exclude, state.dependencies);
compileTemplateExpression(iteratable, exclude, state.dependencies)

node.meta.shouldRender = 1;
},
afterGenerate: function(prop, code, node, parentNode, state) {
// Get information about parameters
Expand Down Expand Up @@ -2221,7 +2223,10 @@
var paramEnd = methodToCall.lastIndexOf(")");
params = methodToCall.substring(paramStart + 1, paramEnd);
methodToCall = methodToCall.substring(0, paramStart);
compileTemplateExpression(params, state.exclude, state.dependencies);

if(compileTemplateExpression(params, state.exclude, state.dependencies) === true) {
node.meta.shouldRender = 1;
}
}

// Generate any modifiers
Expand Down Expand Up @@ -2272,6 +2277,7 @@
code = "function(event) {var modelValue = instance.get(\"" + base + "\");modelValue" + properties + " = " + instanceValue + ";instance.set(\"" + base + "\", modelValue);}";
}

node.meta.shouldRender = 1;
addEventListenerCodeToNode(eventType, code, node);
addDomPropertyCodeToNode(domKey, domValue, node);
}
Expand All @@ -2284,7 +2290,9 @@
var propName = modifiers.shift();
var propValue = prop.value;

compileTemplateExpression(propValue, state.exclude, state.dependencies);
if(compileTemplateExpression(propValue, state.exclude, state.dependencies)) {
node.meta.shouldRender = 1;
}

if(modifiers[0] === "dom") {
addDomPropertyCodeToNode(propName, propValue, node);
Expand Down
2 changes: 1 addition & 1 deletion dist/moon.min.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/compiler/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ const generateProps = function(node, parent, specialDirectivesAfter, state) {
propsCode += generated;
}
}

dynamic = true;
} else if(name[0] === "m" && name[1] === "-") {
hasDirectives = true;
dynamic = true;
Expand Down
10 changes: 7 additions & 3 deletions src/compiler/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,19 @@ const compileTemplateState = function(state) {
}

const compileTemplateExpression = function(expression, exclude, dependencies) {
let dynamic = false;
let references;
while((references = expressionRE.exec(expression)) !== null) {
let reference = references[1];
if(reference !== undefined && dependencies.indexOf(reference) === -1 && exclude.indexOf(reference) === -1) {
dependencies.push(reference);
if(reference !== undefined && dependencies.indexOf(reference) === -1) {
if(exclude.indexOf(reference) === -1) {
dependencies.push(reference);
}
dynamic = true;
}
}

return dependencies;
return dynamic;
}

const scanTemplateStateUntil = function(state, re) {
Expand Down
20 changes: 13 additions & 7 deletions src/directives/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ specialDirectives["m-if"] = {
break;
}
}

node.meta.shouldRender = 1;
},
afterGenerate: function(prop, code, node, parentNode, state) {
const value = prop.value;
Expand All @@ -77,10 +79,6 @@ specialDirectives["m-if"] = {
}
};

specialDirectives["m-else"] = {

};

specialDirectives["m-for"] = {
beforeGenerate: function(prop, node, parentNode, state) {
// Setup Deep Flag to Flatten Array
Expand All @@ -97,7 +95,9 @@ specialDirectives["m-for"] = {
const exclude = state.exclude;
prop.data.forInfo = [iteratable, aliases, exclude];
state.exclude = exclude.concat(aliases.split(","));
compileTemplateExpression(iteratable, exclude, state.dependencies);
compileTemplateExpression(iteratable, exclude, state.dependencies)

node.meta.shouldRender = 1;
},
afterGenerate: function(prop, code, node, parentNode, state) {
// Get information about parameters
Expand Down Expand Up @@ -129,7 +129,10 @@ specialDirectives["m-on"] = {
const paramEnd = methodToCall.lastIndexOf(")");
params = methodToCall.substring(paramStart + 1, paramEnd);
methodToCall = methodToCall.substring(0, paramStart);
compileTemplateExpression(params, state.exclude, state.dependencies);

if(compileTemplateExpression(params, state.exclude, state.dependencies) === true) {
node.meta.shouldRender = 1;
}
}

// Generate any modifiers
Expand Down Expand Up @@ -180,6 +183,7 @@ specialDirectives["m-model"] = {
code = `function(event) {var modelValue = instance.get("${base}");modelValue${properties} = ${instanceValue};instance.set("${base}", modelValue);}`;
}

node.meta.shouldRender = 1;
addEventListenerCodeToNode(eventType, code, node);
addDomPropertyCodeToNode(domKey, domValue, node);
}
Expand All @@ -192,7 +196,9 @@ specialDirectives["m-literal"] = {
const propName = modifiers.shift();
const propValue = prop.value;

compileTemplateExpression(propValue, state.exclude, state.dependencies);
if(compileTemplateExpression(propValue, state.exclude, state.dependencies)) {
node.meta.shouldRender = 1;
}

if(modifiers[0] === "dom") {
addDomPropertyCodeToNode(propName, propValue, node);
Expand Down
Loading

0 comments on commit 3fc782c

Please sign in to comment.