diff --git a/tools/benchmarks/odoo-widgets-12.0/app.js b/tools/benchmarks/odoo-widgets-12.0/app.js index d6842ca1..50cebbe0 100644 --- a/tools/benchmarks/odoo-widgets-12.0/app.js +++ b/tools/benchmarks/odoo-widgets-12.0/app.js @@ -1,4 +1,9 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; odoo.define("app", function(require) { const Widget = require("web.Widget"); @@ -97,14 +102,23 @@ odoo.define("app", function(require) { "click .o_btn_msg.10000": function() { this.addMessages(10000); }, - "click .o_btn_msg.50000": function() { - this.addMessages(50000); + "click .o_btn_msg.30000": function() { + this.addMessages(30000); }, "click .updateSomeMessages": function() { this.updateSomeMessages(); }, "click .clear": function() { this.clear(); + }, + "click .o_multiple": function() { + this.multipleFlag = !this.multipleFlag; + }, + "click .o_clear": function() { + this.clearFlag = !this.clearFlag; + }, + "click .clear-log": function() { + this.$log[0].innerHTML = ""; } }, custom_events: { @@ -116,11 +130,15 @@ odoo.define("app", function(require) { this.widgets = {}; this.isInDom = false; this.messageCount = 0; + this.multipleFlag = false; + this.clearFlag = false; }, start: function() { this.$content = this.$(".content"); this.$msgCount = this.$(".message_count"); + this.$log = this.$(".log-content"); + this.log("Benchmarking odoo widgets, 12.0"); }, on_attach_callback: function() { this.isInDom = true; @@ -144,34 +162,41 @@ odoo.define("app", function(require) { }, addMessages: function(n) { - var self = this; - startMeasure("add " + n); - const defs = []; - const messages = buildData(n); - for (let message of messages) { - const widget = new Message(this, message); - this.widgets[message.id] = widget; - defs.push(widget.appendTo("
")); - } - $.when - .apply($, defs) - .then(function() { - for (let message of messages) { - let widget = self.widgets[message.id]; - dom.append(self.$content, widget.$el, { - in_DOM: this.isInDom, - callbacks: [{ widget: widget }] - }); - } - }) - .then(function() { - self.messageCount += n; - self.updateMessageCount(); - stopMeasure(); - }); + const self = this; + this.benchmark("add " + n, () => { + const defs = []; + const messages = buildData(n); + for (let message of messages) { + const widget = new Message(this, message); + this.widgets[message.id] = widget; + defs.push(widget.appendTo("
")); + } + return $.when + .apply($, defs) + .then(function() { + for (let message of messages) { + let widget = self.widgets[message.id]; + dom.append(self.$content, widget.$el, { + in_DOM: this.isInDom, + callbacks: [{ widget: widget }] + }); + } + }) + .then(function() { + self.messageCount += n; + self.updateMessageCount(); + }); + }); }, clear: function() { startMeasure("clear"); + this._clear(); + stopMeasure(info => { + this.log(info.msg); + }); + }, + + _clear: function() { this.$content.empty(); for (let key in this.widgets) { this.widgets[key].destroy(); @@ -179,15 +204,14 @@ odoo.define("app", function(require) { } this.messageCount = 0; this.updateMessageCount(); - stopMeasure(); }, updateSomeMessages: function() { - startMeasure("update every 10th"); - const widgets = Object.values(this.widgets); - for (let i = 0; i < widgets.length; i += 10) { - widgets[i].update(); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const widgets = Object.values(this.widgets); + for (let i = 0; i < widgets.length; i += 10) { + widgets[i].update(); + } + }); }, _onRemoveMessage: function(ev) { startMeasure("remove message"); @@ -196,6 +220,65 @@ odoo.define("app", function(require) { this.messageCount--; this.updateMessageCount(); stopMeasure(); + }, + + benchmark: function(message, fn, callback) { + if (this.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.clearFlag) { + this._benchmark("clear", this._clear.bind(this), finalize, false); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + }, + + _benchmark: function(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + const benchmark = fn(); + (benchmark && benchmark.then ? benchmark : $.when()).then(() => { + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + }); + }, + + log: function(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.$log[0].appendChild(div); + this.$log[0].scrollTop = this.$log[0].scrollHeight; } }); diff --git a/tools/benchmarks/odoo-widgets-12.0/templates.xml b/tools/benchmarks/odoo-widgets-12.0/templates.xml index 80073246..1384a765 100644 --- a/tools/benchmarks/odoo-widgets-12.0/templates.xml +++ b/tools/benchmarks/odoo-widgets-12.0/templates.xml @@ -1,15 +1,32 @@
-
- Number of msg: 0 +
Actions
+
+ + + + + + +
+
+
+ + +
+
+ + +
+
+
+ Number of messages: 0 +
+
Log (clear)
+
+
- - - - - -
@@ -20,7 +37,7 @@
- +
diff --git a/tools/benchmarks/odoo-widgets-12.3/app.js b/tools/benchmarks/odoo-widgets-12.3/app.js index d6842ca1..af07c3f6 100644 --- a/tools/benchmarks/odoo-widgets-12.3/app.js +++ b/tools/benchmarks/odoo-widgets-12.3/app.js @@ -1,4 +1,9 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; odoo.define("app", function(require) { const Widget = require("web.Widget"); @@ -97,14 +102,23 @@ odoo.define("app", function(require) { "click .o_btn_msg.10000": function() { this.addMessages(10000); }, - "click .o_btn_msg.50000": function() { - this.addMessages(50000); + "click .o_btn_msg.30000": function() { + this.addMessages(30000); }, "click .updateSomeMessages": function() { this.updateSomeMessages(); }, "click .clear": function() { this.clear(); + }, + "click .o_multiple": function() { + this.multipleFlag = !this.multipleFlag; + }, + "click .o_clear": function() { + this.clearFlag = !this.clearFlag; + }, + "click .clear-log": function() { + this.$log[0].innerHTML = ""; } }, custom_events: { @@ -116,11 +130,15 @@ odoo.define("app", function(require) { this.widgets = {}; this.isInDom = false; this.messageCount = 0; + this.multipleFlag = false; + this.clearFlag = false; }, start: function() { this.$content = this.$(".content"); this.$msgCount = this.$(".message_count"); + this.$log = this.$(".log-content"); + this.log("Benchmarking odoo widgets, 12.3"); }, on_attach_callback: function() { this.isInDom = true; @@ -144,34 +162,41 @@ odoo.define("app", function(require) { }, addMessages: function(n) { - var self = this; - startMeasure("add " + n); - const defs = []; - const messages = buildData(n); - for (let message of messages) { - const widget = new Message(this, message); - this.widgets[message.id] = widget; - defs.push(widget.appendTo("
")); - } - $.when - .apply($, defs) - .then(function() { - for (let message of messages) { - let widget = self.widgets[message.id]; - dom.append(self.$content, widget.$el, { - in_DOM: this.isInDom, - callbacks: [{ widget: widget }] - }); - } - }) - .then(function() { - self.messageCount += n; - self.updateMessageCount(); - stopMeasure(); - }); + const self = this; + this.benchmark("add " + n, () => { + const defs = []; + const messages = buildData(n); + for (let message of messages) { + const widget = new Message(this, message); + this.widgets[message.id] = widget; + defs.push(widget.appendTo("
")); + } + return $.when + .apply($, defs) + .then(function() { + for (let message of messages) { + let widget = self.widgets[message.id]; + dom.append(self.$content, widget.$el, { + in_DOM: this.isInDom, + callbacks: [{ widget: widget }] + }); + } + }) + .then(function() { + self.messageCount += n; + self.updateMessageCount(); + }); + }); }, clear: function() { startMeasure("clear"); + this._clear(); + stopMeasure(info => { + this.log(info.msg); + }); + }, + + _clear: function() { this.$content.empty(); for (let key in this.widgets) { this.widgets[key].destroy(); @@ -179,15 +204,14 @@ odoo.define("app", function(require) { } this.messageCount = 0; this.updateMessageCount(); - stopMeasure(); }, updateSomeMessages: function() { - startMeasure("update every 10th"); - const widgets = Object.values(this.widgets); - for (let i = 0; i < widgets.length; i += 10) { - widgets[i].update(); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const widgets = Object.values(this.widgets); + for (let i = 0; i < widgets.length; i += 10) { + widgets[i].update(); + } + }); }, _onRemoveMessage: function(ev) { startMeasure("remove message"); @@ -196,6 +220,65 @@ odoo.define("app", function(require) { this.messageCount--; this.updateMessageCount(); stopMeasure(); + }, + + benchmark: function(message, fn, callback) { + if (this.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.clearFlag) { + this._benchmark("clear", this._clear.bind(this), finalize, false); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + }, + + _benchmark: function(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + const benchmark = fn(); + (benchmark && benchmark.then ? benchmark : $.when()).then(() => { + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + }); + }, + + log: function(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.$log[0].appendChild(div); + this.$log[0].scrollTop = this.$log[0].scrollHeight; } }); diff --git a/tools/benchmarks/odoo-widgets-12.3/templates.xml b/tools/benchmarks/odoo-widgets-12.3/templates.xml index 80073246..1384a765 100644 --- a/tools/benchmarks/odoo-widgets-12.3/templates.xml +++ b/tools/benchmarks/odoo-widgets-12.3/templates.xml @@ -1,15 +1,32 @@
-
- Number of msg: 0 +
Actions
+
+ + + + + + +
+
+
+ + +
+
+ + +
+
+
+ Number of messages: 0 +
+
Log (clear)
+
+
- - - - - -
@@ -20,7 +37,7 @@
- +
diff --git a/tools/benchmarks/owl-0.10.0/app.js b/tools/benchmarks/owl-0.10.0/app.js index e589b499..f89a020a 100644 --- a/tools/benchmarks/owl-0.10.0/app.js +++ b/tools/benchmarks/owl-0.10.0/app.js @@ -1,11 +1,16 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; + template = "Counter"; increment() { this.state.counter++; @@ -16,8 +21,8 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; + template = "Message"; shouldUpdate(nextProps) { return nextProps !== this.props; @@ -33,39 +38,123 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + template = "App"; + + mounted() { + this.log( + `Benchmarking Owl v${owl._version} (build date: ${ + owl._date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.10.0/templates.xml b/tools/benchmarks/owl-0.10.0/templates.xml index 351fd84f..699ebea3 100644 --- a/tools/benchmarks/owl-0.10.0/templates.xml +++ b/tools/benchmarks/owl-0.10.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-0.11.0/app.js b/tools/benchmarks/owl-0.11.0/app.js index e589b499..ed6e68d7 100644 --- a/tools/benchmarks/owl-0.11.0/app.js +++ b/tools/benchmarks/owl-0.11.0/app.js @@ -1,10 +1,14 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; increment() { @@ -16,7 +20,6 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; shouldUpdate(nextProps) { @@ -33,39 +36,122 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + + mounted() { + this.log( + `Benchmarking Owl v${owl._version} (build date: ${ + owl._date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.11.0/templates.xml b/tools/benchmarks/owl-0.11.0/templates.xml index 351fd84f..699ebea3 100644 --- a/tools/benchmarks/owl-0.11.0/templates.xml +++ b/tools/benchmarks/owl-0.11.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-0.12.0/app.js b/tools/benchmarks/owl-0.12.0/app.js index e589b499..5410383e 100644 --- a/tools/benchmarks/owl-0.12.0/app.js +++ b/tools/benchmarks/owl-0.12.0/app.js @@ -1,10 +1,14 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; increment() { @@ -16,7 +20,6 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; shouldUpdate(nextProps) { @@ -33,39 +36,122 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + + mounted() { + this.log( + `Benchmarking Owl v${owl.__info__.version} (build date: ${ + owl.__info__.date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this.benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.12.0/templates.xml b/tools/benchmarks/owl-0.12.0/templates.xml index 351fd84f..2207465d 100644 --- a/tools/benchmarks/owl-0.12.0/templates.xml +++ b/tools/benchmarks/owl-0.12.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-0.13.0/app.js b/tools/benchmarks/owl-0.13.0/app.js index 6a9693b0..9734c34c 100644 --- a/tools/benchmarks/owl-0.13.0/app.js +++ b/tools/benchmarks/owl-0.13.0/app.js @@ -1,10 +1,14 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; increment() { @@ -16,15 +20,14 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; shouldUpdate(nextProps) { return nextProps.message !== this.props.message; } removeMessage() { - this.trigger("remove_message", { - id: this.props.id + this.trigger("remove-message", { + id: this.props.message.id }); } } @@ -33,39 +36,122 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + + mounted() { + this.log( + `Benchmarking Owl v${owl.__info__.version} (build date: ${ + owl.__info__.date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += "!!!"; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } - removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + removeMessage(event) { + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === event.detail.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.13.0/templates.xml b/tools/benchmarks/owl-0.13.0/templates.xml index a1bff7de..b53a3dac 100644 --- a/tools/benchmarks/owl-0.13.0/templates.xml +++ b/tools/benchmarks/owl-0.13.0/templates.xml @@ -1,33 +1,49 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
- +
-
+
-
+
diff --git a/tools/benchmarks/owl-0.7.0/app.js b/tools/benchmarks/owl-0.7.0/app.js index 6eddb25d..f89a020a 100644 --- a/tools/benchmarks/owl-0.7.0/app.js +++ b/tools/benchmarks/owl-0.7.0/app.js @@ -1,11 +1,16 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; + template = "Counter"; increment() { this.state.counter++; @@ -16,13 +21,12 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; + template = "Message"; shouldUpdate(nextProps) { return nextProps !== this.props; } - removeMessage() { this.trigger("remove_message", { id: this.props.id @@ -34,39 +38,123 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + template = "App"; + + mounted() { + this.log( + `Benchmarking Owl v${owl._version} (build date: ${ + owl._date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure('remove message'); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.7.0/templates.xml b/tools/benchmarks/owl-0.7.0/templates.xml index 351fd84f..699ebea3 100644 --- a/tools/benchmarks/owl-0.7.0/templates.xml +++ b/tools/benchmarks/owl-0.7.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-0.8.0/app.js b/tools/benchmarks/owl-0.8.0/app.js index e589b499..f89a020a 100644 --- a/tools/benchmarks/owl-0.8.0/app.js +++ b/tools/benchmarks/owl-0.8.0/app.js @@ -1,11 +1,16 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; + template = "Counter"; increment() { this.state.counter++; @@ -16,8 +21,8 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; + template = "Message"; shouldUpdate(nextProps) { return nextProps !== this.props; @@ -33,39 +38,123 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + template = "App"; + + mounted() { + this.log( + `Benchmarking Owl v${owl._version} (build date: ${ + owl._date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.8.0/templates.xml b/tools/benchmarks/owl-0.8.0/templates.xml index 351fd84f..699ebea3 100644 --- a/tools/benchmarks/owl-0.8.0/templates.xml +++ b/tools/benchmarks/owl-0.8.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-0.9.0/app.js b/tools/benchmarks/owl-0.9.0/app.js index e589b499..f89a020a 100644 --- a/tools/benchmarks/owl-0.9.0/app.js +++ b/tools/benchmarks/owl-0.9.0/app.js @@ -1,11 +1,16 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget //------------------------------------------------------------------------------ class Counter extends owl.Component { - template = "counter"; state = { counter: 0 }; + template = "Counter"; increment() { this.state.counter++; @@ -16,8 +21,8 @@ class Counter extends owl.Component { // Message Widget //------------------------------------------------------------------------------ class Message extends owl.Component { - template = "message"; widgets = { Counter }; + template = "Message"; shouldUpdate(nextProps) { return nextProps !== this.props; @@ -33,39 +38,123 @@ class Message extends owl.Component { // Root Widget //------------------------------------------------------------------------------ class App extends owl.Component { - template = "root"; widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + template = "App"; + + mounted() { + this.log( + `Benchmarking Owl v${owl._version} (build date: ${ + owl._date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - this.set(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + this.set(messages, i, msg); + } + }); } removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === data.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-0.9.0/templates.xml b/tools/benchmarks/owl-0.9.0/templates.xml index 351fd84f..699ebea3 100644 --- a/tools/benchmarks/owl-0.9.0/templates.xml +++ b/tools/benchmarks/owl-0.9.0/templates.xml @@ -1,16 +1,34 @@ -
+
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
@@ -18,14 +36,14 @@
-
+
-
+
diff --git a/tools/benchmarks/owl-master/app.js b/tools/benchmarks/owl-master/app.js index 4ea419b6..34093066 100644 --- a/tools/benchmarks/owl-master/app.js +++ b/tools/benchmarks/owl-master/app.js @@ -1,4 +1,9 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Likes Counter Widget @@ -18,11 +23,11 @@ class Message extends owl.Component { widgets = { Counter }; shouldUpdate(nextProps) { - return nextProps !== this.props; + return nextProps.message !== this.props.message; } removeMessage() { - this.trigger("remove_message", { - id: this.props.id + this.trigger("remove-message", { + id: this.props.message.id }); } } @@ -32,38 +37,122 @@ class Message extends owl.Component { //------------------------------------------------------------------------------ class App extends owl.Component { widgets = { Message }; - state = { messages: [] }; + state = { messages: [], multipleFlag: false, clearAfterFlag: false }; + + mounted() { + this.log( + `Benchmarking Owl v${owl.__info__.version} (build date: ${ + owl.__info__.date + })` + ); + } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.state.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.state.messages.push.apply(this.state.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.state.messages.push.apply(this.state.messages, newMessages); + }); } clear() { - startMeasure("clear"); - this.state.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.state.messages = []; + }); } updateSomeMessages() { - startMeasure("update every 10th"); - const setState = owl.Observer.set; - const messages = this.state.messages; - for (let i = 0; i < this.state.messages.length; i += 10) { - const msg = Object.assign({}, messages[i]); - msg.author += '!!!'; - setState(messages, i, msg); - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const setState = owl.Observer.set; + const messages = this.state.messages; + for (let i = 0; i < this.state.messages.length; i += 10) { + const msg = Object.assign({}, messages[i]); + msg.author += "!!!"; + setState(messages, i, msg); + } + }); } - removeMessage(data) { - startMeasure("remove message"); - const index = this.state.messages.findIndex(m => m.id === data.id); - this.state.messages.splice(index, 1); - stopMeasure(); + removeMessage(event) { + this.benchmark("remove message", () => { + const index = this.state.messages.findIndex(m => m.id === event.detail.id); + this.state.messages.splice(index, 1); + }); + } + + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.log.appendChild(div); + this.refs.log.scrollTop = this.refs.log.scrollHeight; + } + + clearLog() { + this.refs.log.innerHTML = ""; + } + + toggleMultiple() { + this.state.multipleFlag = !this.state.multipleFlag; + } + + toggleClear() { + this.state.clearAfterFlag = !this.state.clearAfterFlag; } } diff --git a/tools/benchmarks/owl-master/index.html b/tools/benchmarks/owl-master/index.html index 332e949e..1bb955f1 100644 --- a/tools/benchmarks/owl-master/index.html +++ b/tools/benchmarks/owl-master/index.html @@ -7,7 +7,6 @@ -
diff --git a/tools/benchmarks/owl-master/templates.xml b/tools/benchmarks/owl-master/templates.xml index 94306687..b53a3dac 100644 --- a/tools/benchmarks/owl-master/templates.xml +++ b/tools/benchmarks/owl-master/templates.xml @@ -1,18 +1,36 @@
-
Number of msg:
+
Actions
+
- - - - + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages:
+
+
Log (clear)
+
+
+
-
+
- +
diff --git a/tools/benchmarks/react/app.js b/tools/benchmarks/react/app.js index 3e543b04..31416fad 100644 --- a/tools/benchmarks/react/app.js +++ b/tools/benchmarks/react/app.js @@ -1,4 +1,9 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Counter Widget @@ -86,9 +91,33 @@ class Main extends React.Component { constructor(props) { super(props); this.state = { - messages: [] + messages: [], + multipleFlag: false, + clearAfterFlag: false }; this.removeMessage = this.removeMessage.bind(this); + this.toggleMultipleFlag = this.toggleMultipleFlag.bind(this); + this.toggleClearAfterFlag = this.toggleClearAfterFlag.bind(this); + } + + componentDidMount() { + this.log(`Benchmarking React v${React.version}`); + } + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.refs.logref.appendChild(div); + this.refs.logref.scrollTop = this.refs.logref.scrollHeight; + } + + toggleMultipleFlag() { + this.setState({ multipleFlag: !this.state.multipleFlag }); + } + toggleClearAfterFlag() { + this.setState({ clearAfterFlag: !this.state.clearAfterFlag }); } render() { @@ -109,53 +138,98 @@ class Main extends React.Component { { className: "left-thing" }, + React.createElement("div", { className: "title" }, "Actions"), React.createElement( "div", - null, - "Number of msg: ", + { className: "panel" }, + React.createElement( + "button", + { + onClick: _ => this.addMessages(100) + }, + "Add 100 messages" + ), + React.createElement( + "button", + { + onClick: _ => this.addMessages(1000) + }, + "Add 1k messages" + ), + React.createElement( + "button", + { + onClick: _ => this.addMessages(10000) + }, + "Add 10k messages" + ), + React.createElement( + "button", + { + onClick: _ => this.addMessages(30000) + }, + "Add 30k messages" + ), + React.createElement( + "button", + { + onClick: _ => this.updateSomeMessages() + }, + "Update every 10th message" + ), + React.createElement( + "button", + { + onClick: _ => this.clear() + }, + "Clear" + ) + ), + React.createElement( + "div", + { className: "flags" }, + React.createElement( + "div", + null, + React.createElement("input", { + type: "checkbox", + id: "multipleFlag", + value: this.state.multipleFlag, + onChange: this.toggleMultipleFlag + }), + React.createElement("label", { for: "multipleFlag" }, " Do it 20x") + ), + React.createElement( + "div", + null, + React.createElement("input", { + type: "checkbox", + id: "clearFlag", + value: this.state.clearAfterFlag, + onChange: this.toggleClearAfterFlag + }), + React.createElement("label", { for: "clearFlag" }, " Clear after") + ) + ), + React.createElement( + "div", + { className: "info" }, + "Number of messages: ", this.state.messages.length ), React.createElement( - "button", - { - onClick: _ => this.addMessages(100) - }, - "Add 100 messages" + "div", + { className: "title" }, + "Log ", + React.createElement("span", { className: "clear-log" }, "(clear)") ), React.createElement( - "button", - { - onClick: _ => this.addMessages(1000) - }, - "Add 1000 messages" - ), - React.createElement( - "button", - { - onClick: _ => this.addMessages(10000) - }, - "Add 10000 messages" - ), - React.createElement( - "button", - { - onClick: _ => this.addMessages(50000) - }, - "Add 50000 messages" - ), - React.createElement( - "button", - { - onClick: _ => this.updateSomeMessages() - }, - "Update every 10th messags" - ), - React.createElement( - "button", - { - onClick: _ => this.clear() - }, - "Clear" + "div", + { className: "log" }, + React.createElement("div", { + className: "log-content", + ref: "logref" + }) ) ), React.createElement( @@ -175,30 +249,30 @@ class Main extends React.Component { } addMessages(n) { - startMeasure("add " + n); - const newMessages = this.state.messages.concat(buildData(n)); - this.setState({ - messages: newMessages + this.benchmark("add " + n, () => { + const newMessages = this.state.messages.concat(buildData(n)); + this.setState({ + messages: newMessages + }); }); - stopMeasure(); } clear() { - startMeasure("clear"); - this.setState({ - messages: [] + this._benchmark("clear", () => { + this.setState({ + messages: [] + }); }); - stopMeasure(); } updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.state.messages; - for (let i = 0; i < messages.length; i += 10) { - messages[i].author += "!!!"; - } - this.forceUpdate(); - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.state.messages; + for (let i = 0; i < messages.length; i += 10) { + messages[i].author += "!!!"; + } + this.forceUpdate(); + }); } removeMessage(id) { @@ -211,11 +285,61 @@ class Main extends React.Component { }); stopMeasure(); } + + benchmark(message, fn, callback) { + if (this.state.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + if (this.state.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.setState({ messages: [] }); + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + } + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); + } } //----------------------------- // INIT //----------------------------- -ReactDOM.render( - React.createElement(Main, null), - document.getElementById("main") -); +ReactDOM.render(React.createElement(Main, null), document.body); diff --git a/tools/benchmarks/shared/main.css b/tools/benchmarks/shared/main.css index 51e1c065..e76fbf8a 100755 --- a/tools/benchmarks/shared/main.css +++ b/tools/benchmarks/shared/main.css @@ -1,26 +1,91 @@ -.main { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; +html, +body { + height: 100%; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, + sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +} +body { + margin: 0; +} +.main { + height: 100%; + + font-size: 14px; display: grid; - grid-template-columns: 220px 1fr; + grid-template-columns: 640px 1fr; } .left-thing { background-color: gray; - padding: 20px; color: white; + display: flex; + flex-direction: column; } -.left-thing button { - width: 100%; +.left-thing hr { + width: 100%; + flex: 0 0 auto; +} + +.title { + padding: 10px; + font-size: 20px; + font-weight: bold; + flex: 0 0 auto; +} + +.panel { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + flex: 0 0 auto; +} + +.panel button { + flex: 0 0 32%; + height: 32px; + margin-top: 4px; + margin-bottom: 4px; + font-size: 14px; + margin-left: 3px; + margin-right: 3px; +} + +.info { + padding: 10px; + flex: 0 0 auto; +} + +.flags { + padding: 10px; +} +.log { + flex: 1 1 auto; + position: relative; +} + +.log-content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: auto; +} + +.bold { + font-weight: bold; +} + +.clear-log { + font-size: 14px; + color: #eeeeee; + cursor: pointer; } .right-thing { - padding: 20px; overflow: auto; } diff --git a/tools/benchmarks/shared/utils.js b/tools/benchmarks/shared/utils.js index d24b565c..89e15dac 100644 --- a/tools/benchmarks/shared/utils.js +++ b/tools/benchmarks/shared/utils.js @@ -31,19 +31,28 @@ export function buildData(n = 1000) { //------------------------------------------------------------------------------ // Measuring helpers //------------------------------------------------------------------------------ +export function formatNumber(n) { + return Number(n).toFixed(); +} + let startTime; let lastMeasure; export function startMeasure(descr) { startTime = performance.now(); lastMeasure = descr; } -export function stopMeasure() { +export function stopMeasure(cb) { let last = lastMeasure; if (lastMeasure) { window.setTimeout(function() { lastMeasure = null; const stop = performance.now(); - console.log(`[${last}] took ${Number(stop - startTime).toFixed()}ms`); + const delta = stop - startTime; + const msg = `[${last}] took ${formatNumber(delta)}ms`; + console.log(msg); + if (cb) { + cb({msg, delta}); + } }, 0); } } diff --git a/tools/benchmarks/vue/app.js b/tools/benchmarks/vue/app.js index 7e3b42b8..f11f8e52 100644 --- a/tools/benchmarks/vue/app.js +++ b/tools/benchmarks/vue/app.js @@ -1,4 +1,9 @@ -import { buildData, startMeasure, stopMeasure } from "../shared/utils.js"; +import { + buildData, + startMeasure, + stopMeasure, + formatNumber +} from "../shared/utils.js"; //------------------------------------------------------------------------------ // Counter Widget @@ -45,29 +50,36 @@ Vue.component("my-message", { const App = { name: "App", data() { - return { messages: [] }; + return { messages: [], multipleFlag: false, clearAfterFlag: false }; + }, + mounted() { + this.log(`Benchmarking Vue v${Vue.version}`); }, methods: { addMessages(n) { - startMeasure("add " + n); - const newMessages = buildData(n); - this.messages.push.apply(this.messages, newMessages); - stopMeasure(); + this.benchmark("add " + n, () => { + const newMessages = buildData(n); + this.messages.push.apply(this.messages, newMessages); + }); }, clear() { - startMeasure("clear"); - this.messages = []; - stopMeasure(); + this._benchmark("clear", () => { + this.messages = []; + }); + }, + + clearLog() { + this.$refs.log.innerHTML = ""; }, updateSomeMessages() { - startMeasure("update every 10th"); - const messages = this.messages; - for (let i = 0; i < this.messages.length; i += 10) { - messages[i].author += "!!!"; - } - stopMeasure(); + this.benchmark("update every 10th", () => { + const messages = this.messages; + for (let i = 0; i < this.messages.length; i += 10) { + messages[i].author += "!!!"; + } + }); }, removeMessage(id) { @@ -75,18 +87,98 @@ const App = { const index = this.messages.findIndex(m => m.id === id); this.messages.splice(index, 1); stopMeasure(); + }, + log(str, isBold) { + const div = document.createElement("div"); + if (isBold) { + div.classList.add("bold"); + } + div.textContent = `> ${str}`; + this.$refs.log.appendChild(div); + this.$refs.log.scrollTop = this.$refs.log.scrollHeight; + }, + benchmark(message, fn, callback) { + if (this.multipleFlag) { + const N = 20; + let n = N; + let total = 0; + let cb = info => { + let finalize = () => { + n--; + total += info.delta; + if (n === 0) { + const avg = total / N; + this.log(`Average: ${formatNumber(avg)}ms`, true); + if (callback) { + callback(); + } + } else { + this._benchmark(message, fn, cb); + } + }; + + if (this.clearAfterFlag) { + this._benchmark( + "clear", + () => { + this.messages = []; + }, + finalize, + false + ); + } else { + finalize(); + } + }; + this._benchmark(message, fn, cb); + } else { + this._benchmark(message, fn, callback); + } + }, + + _benchmark(message, fn, cb, log = true) { + setTimeout(() => { + startMeasure(message); + fn(); + stopMeasure(info => { + if (log) { + this.log(info.msg); + } + if (cb) { + cb(info); + } + }); + }, 10); } }, template: `
-
Number of msg: {{messages.length}}
- - - - - - +
Actions
+
+ + + + + + +
+
+
+ + +
+
+ + +
+
+
Number of messages: {{messages.length}}
+
+
Log (clear)
+
+
+
diff --git a/tools/index.html b/tools/index.html index ca5b800f..9de2991d 100644 --- a/tools/index.html +++ b/tools/index.html @@ -2,7 +2,7 @@ - OWL Extras + OWL Tools diff --git a/tools/main.css b/tools/main.css index cf1026b5..17271297 100644 --- a/tools/main.css +++ b/tools/main.css @@ -1,5 +1,9 @@ +html, body { - font-family: sans-serif; + height: 100%; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, + sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; } .title,