mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
@@ -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) {
|
odoo.define("app", function(require) {
|
||||||
const Widget = require("web.Widget");
|
const Widget = require("web.Widget");
|
||||||
@@ -97,14 +102,23 @@ odoo.define("app", function(require) {
|
|||||||
"click .o_btn_msg.10000": function() {
|
"click .o_btn_msg.10000": function() {
|
||||||
this.addMessages(10000);
|
this.addMessages(10000);
|
||||||
},
|
},
|
||||||
"click .o_btn_msg.50000": function() {
|
"click .o_btn_msg.30000": function() {
|
||||||
this.addMessages(50000);
|
this.addMessages(30000);
|
||||||
},
|
},
|
||||||
"click .updateSomeMessages": function() {
|
"click .updateSomeMessages": function() {
|
||||||
this.updateSomeMessages();
|
this.updateSomeMessages();
|
||||||
},
|
},
|
||||||
"click .clear": function() {
|
"click .clear": function() {
|
||||||
this.clear();
|
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: {
|
custom_events: {
|
||||||
@@ -116,11 +130,15 @@ odoo.define("app", function(require) {
|
|||||||
this.widgets = {};
|
this.widgets = {};
|
||||||
this.isInDom = false;
|
this.isInDom = false;
|
||||||
this.messageCount = 0;
|
this.messageCount = 0;
|
||||||
|
this.multipleFlag = false;
|
||||||
|
this.clearFlag = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
this.$content = this.$(".content");
|
this.$content = this.$(".content");
|
||||||
this.$msgCount = this.$(".message_count");
|
this.$msgCount = this.$(".message_count");
|
||||||
|
this.$log = this.$(".log-content");
|
||||||
|
this.log("Benchmarking odoo widgets, 12.0");
|
||||||
},
|
},
|
||||||
on_attach_callback: function() {
|
on_attach_callback: function() {
|
||||||
this.isInDom = true;
|
this.isInDom = true;
|
||||||
@@ -144,8 +162,8 @@ odoo.define("app", function(require) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
addMessages: function(n) {
|
addMessages: function(n) {
|
||||||
var self = this;
|
const self = this;
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const defs = [];
|
const defs = [];
|
||||||
const messages = buildData(n);
|
const messages = buildData(n);
|
||||||
for (let message of messages) {
|
for (let message of messages) {
|
||||||
@@ -153,7 +171,7 @@ odoo.define("app", function(require) {
|
|||||||
this.widgets[message.id] = widget;
|
this.widgets[message.id] = widget;
|
||||||
defs.push(widget.appendTo("<div>"));
|
defs.push(widget.appendTo("<div>"));
|
||||||
}
|
}
|
||||||
$.when
|
return $.when
|
||||||
.apply($, defs)
|
.apply($, defs)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
for (let message of messages) {
|
for (let message of messages) {
|
||||||
@@ -167,11 +185,18 @@ odoo.define("app", function(require) {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
self.messageCount += n;
|
self.messageCount += n;
|
||||||
self.updateMessageCount();
|
self.updateMessageCount();
|
||||||
stopMeasure();
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
clear: function() {
|
clear: function() {
|
||||||
startMeasure("clear");
|
startMeasure("clear");
|
||||||
|
this._clear();
|
||||||
|
stopMeasure(info => {
|
||||||
|
this.log(info.msg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_clear: function() {
|
||||||
this.$content.empty();
|
this.$content.empty();
|
||||||
for (let key in this.widgets) {
|
for (let key in this.widgets) {
|
||||||
this.widgets[key].destroy();
|
this.widgets[key].destroy();
|
||||||
@@ -179,15 +204,14 @@ odoo.define("app", function(require) {
|
|||||||
}
|
}
|
||||||
this.messageCount = 0;
|
this.messageCount = 0;
|
||||||
this.updateMessageCount();
|
this.updateMessageCount();
|
||||||
stopMeasure();
|
|
||||||
},
|
},
|
||||||
updateSomeMessages: function() {
|
updateSomeMessages: function() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const widgets = Object.values(this.widgets);
|
const widgets = Object.values(this.widgets);
|
||||||
for (let i = 0; i < widgets.length; i += 10) {
|
for (let i = 0; i < widgets.length; i += 10) {
|
||||||
widgets[i].update();
|
widgets[i].update();
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
},
|
},
|
||||||
_onRemoveMessage: function(ev) {
|
_onRemoveMessage: function(ev) {
|
||||||
startMeasure("remove message");
|
startMeasure("remove message");
|
||||||
@@ -196,6 +220,65 @@ odoo.define("app", function(require) {
|
|||||||
this.messageCount--;
|
this.messageCount--;
|
||||||
this.updateMessageCount();
|
this.updateMessageCount();
|
||||||
stopMeasure();
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,33 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div class="main" t-name="root">
|
<div class="main" t-name="root">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div class="message_count">
|
<div class="title">Actions</div>
|
||||||
Number of msg: 0
|
<div class="panel">
|
||||||
</div>
|
|
||||||
<button class="o_btn_msg 100">Add 100 messages</button>
|
<button class="o_btn_msg 100">Add 100 messages</button>
|
||||||
<button class="o_btn_msg 1000">Add 1000 messages</button>
|
<button class="o_btn_msg 1000">Add 1k messages</button>
|
||||||
<button class="o_btn_msg 10000">Add 10000 messages</button>
|
<button class="o_btn_msg 10000">Add 10k messages</button>
|
||||||
<button class="o_btn_msg 50000">Add 50000 messages</button>
|
<button class="o_btn_msg 30000">Add 30k messages</button>
|
||||||
<button class="updateSomeMessages">Update every 10th message</button>
|
<button class="updateSomeMessages">Update every 10th message</button>
|
||||||
<button class="clear">Clear</button>
|
<button class="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="o_multiple" id="multipleflag" />
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="o_clear" id="clearFlag" />
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info message_count">
|
||||||
|
Number of messages: 0
|
||||||
|
</div>
|
||||||
|
<div class="title">Log <span class="clear-log">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
</div>
|
</div>
|
||||||
@@ -20,7 +37,7 @@
|
|||||||
<div t-name="message" class="message">
|
<div t-name="message" class="message">
|
||||||
<span class="author"><t t-esc="widget.author"/></span>
|
<span class="author"><t t-esc="widget.author"/></span>
|
||||||
<span class="msg"><t t-esc="widget.msg"/></span>
|
<span class="msg"><t t-esc="widget.msg"/></span>
|
||||||
<button class="remove" >Remove</button>
|
<button class="remove">Remove</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="counter">
|
||||||
|
|||||||
@@ -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) {
|
odoo.define("app", function(require) {
|
||||||
const Widget = require("web.Widget");
|
const Widget = require("web.Widget");
|
||||||
@@ -97,14 +102,23 @@ odoo.define("app", function(require) {
|
|||||||
"click .o_btn_msg.10000": function() {
|
"click .o_btn_msg.10000": function() {
|
||||||
this.addMessages(10000);
|
this.addMessages(10000);
|
||||||
},
|
},
|
||||||
"click .o_btn_msg.50000": function() {
|
"click .o_btn_msg.30000": function() {
|
||||||
this.addMessages(50000);
|
this.addMessages(30000);
|
||||||
},
|
},
|
||||||
"click .updateSomeMessages": function() {
|
"click .updateSomeMessages": function() {
|
||||||
this.updateSomeMessages();
|
this.updateSomeMessages();
|
||||||
},
|
},
|
||||||
"click .clear": function() {
|
"click .clear": function() {
|
||||||
this.clear();
|
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: {
|
custom_events: {
|
||||||
@@ -116,11 +130,15 @@ odoo.define("app", function(require) {
|
|||||||
this.widgets = {};
|
this.widgets = {};
|
||||||
this.isInDom = false;
|
this.isInDom = false;
|
||||||
this.messageCount = 0;
|
this.messageCount = 0;
|
||||||
|
this.multipleFlag = false;
|
||||||
|
this.clearFlag = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
this.$content = this.$(".content");
|
this.$content = this.$(".content");
|
||||||
this.$msgCount = this.$(".message_count");
|
this.$msgCount = this.$(".message_count");
|
||||||
|
this.$log = this.$(".log-content");
|
||||||
|
this.log("Benchmarking odoo widgets, 12.3");
|
||||||
},
|
},
|
||||||
on_attach_callback: function() {
|
on_attach_callback: function() {
|
||||||
this.isInDom = true;
|
this.isInDom = true;
|
||||||
@@ -144,8 +162,8 @@ odoo.define("app", function(require) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
addMessages: function(n) {
|
addMessages: function(n) {
|
||||||
var self = this;
|
const self = this;
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const defs = [];
|
const defs = [];
|
||||||
const messages = buildData(n);
|
const messages = buildData(n);
|
||||||
for (let message of messages) {
|
for (let message of messages) {
|
||||||
@@ -153,7 +171,7 @@ odoo.define("app", function(require) {
|
|||||||
this.widgets[message.id] = widget;
|
this.widgets[message.id] = widget;
|
||||||
defs.push(widget.appendTo("<div>"));
|
defs.push(widget.appendTo("<div>"));
|
||||||
}
|
}
|
||||||
$.when
|
return $.when
|
||||||
.apply($, defs)
|
.apply($, defs)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
for (let message of messages) {
|
for (let message of messages) {
|
||||||
@@ -167,11 +185,18 @@ odoo.define("app", function(require) {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
self.messageCount += n;
|
self.messageCount += n;
|
||||||
self.updateMessageCount();
|
self.updateMessageCount();
|
||||||
stopMeasure();
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
clear: function() {
|
clear: function() {
|
||||||
startMeasure("clear");
|
startMeasure("clear");
|
||||||
|
this._clear();
|
||||||
|
stopMeasure(info => {
|
||||||
|
this.log(info.msg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_clear: function() {
|
||||||
this.$content.empty();
|
this.$content.empty();
|
||||||
for (let key in this.widgets) {
|
for (let key in this.widgets) {
|
||||||
this.widgets[key].destroy();
|
this.widgets[key].destroy();
|
||||||
@@ -179,15 +204,14 @@ odoo.define("app", function(require) {
|
|||||||
}
|
}
|
||||||
this.messageCount = 0;
|
this.messageCount = 0;
|
||||||
this.updateMessageCount();
|
this.updateMessageCount();
|
||||||
stopMeasure();
|
|
||||||
},
|
},
|
||||||
updateSomeMessages: function() {
|
updateSomeMessages: function() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const widgets = Object.values(this.widgets);
|
const widgets = Object.values(this.widgets);
|
||||||
for (let i = 0; i < widgets.length; i += 10) {
|
for (let i = 0; i < widgets.length; i += 10) {
|
||||||
widgets[i].update();
|
widgets[i].update();
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
},
|
},
|
||||||
_onRemoveMessage: function(ev) {
|
_onRemoveMessage: function(ev) {
|
||||||
startMeasure("remove message");
|
startMeasure("remove message");
|
||||||
@@ -196,6 +220,65 @@ odoo.define("app", function(require) {
|
|||||||
this.messageCount--;
|
this.messageCount--;
|
||||||
this.updateMessageCount();
|
this.updateMessageCount();
|
||||||
stopMeasure();
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,33 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div class="main" t-name="root">
|
<div class="main" t-name="root">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div class="message_count">
|
<div class="title">Actions</div>
|
||||||
Number of msg: 0
|
<div class="panel">
|
||||||
</div>
|
|
||||||
<button class="o_btn_msg 100">Add 100 messages</button>
|
<button class="o_btn_msg 100">Add 100 messages</button>
|
||||||
<button class="o_btn_msg 1000">Add 1000 messages</button>
|
<button class="o_btn_msg 1000">Add 1k messages</button>
|
||||||
<button class="o_btn_msg 10000">Add 10000 messages</button>
|
<button class="o_btn_msg 10000">Add 10k messages</button>
|
||||||
<button class="o_btn_msg 50000">Add 50000 messages</button>
|
<button class="o_btn_msg 30000">Add 30k messages</button>
|
||||||
<button class="updateSomeMessages">Update every 10th message</button>
|
<button class="updateSomeMessages">Update every 10th message</button>
|
||||||
<button class="clear">Clear</button>
|
<button class="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="o_multiple" id="multipleflag" />
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="o_clear" id="clearFlag" />
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info message_count">
|
||||||
|
Number of messages: 0
|
||||||
|
</div>
|
||||||
|
<div class="title">Log <span class="clear-log">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
</div>
|
</div>
|
||||||
@@ -20,7 +37,7 @@
|
|||||||
<div t-name="message" class="message">
|
<div t-name="message" class="message">
|
||||||
<span class="author"><t t-esc="widget.author"/></span>
|
<span class="author"><t t-esc="widget.author"/></span>
|
||||||
<span class="msg"><t t-esc="widget.msg"/></span>
|
<span class="msg"><t t-esc="widget.msg"/></span>
|
||||||
<button class="remove" >Remove</button>
|
<button class="remove">Remove</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="counter">
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
template = "Counter";
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
this.state.counter++;
|
this.state.counter++;
|
||||||
@@ -16,8 +21,8 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
template = "Message";
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps !== this.props;
|
return nextProps !== this.props;
|
||||||
@@ -33,39 +38,123 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="'log'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
@@ -16,7 +20,6 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
@@ -33,39 +36,122 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="'log'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
@@ -16,7 +20,6 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
@@ -33,39 +36,122 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this.benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="log"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
@@ -16,15 +20,14 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps.message !== this.props.message;
|
return nextProps.message !== this.props.message;
|
||||||
}
|
}
|
||||||
removeMessage() {
|
removeMessage() {
|
||||||
this.trigger("remove_message", {
|
this.trigger("remove-message", {
|
||||||
id: this.props.id
|
id: this.props.message.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,39 +36,122 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += "!!!";
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(event) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === event.detail.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,49 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="log"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id"
|
<t t-widget="Message" t-key="message.id" message="message"/>
|
||||||
message="message"
|
|
||||||
t-on-remove_message="removeMessage"/>
|
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.message.author"/></span>
|
<span class="author"><t t-esc="props.message.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.message.msg"/></span>
|
<span class="msg"><t t-esc="props.message.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
template = "Counter";
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
this.state.counter++;
|
this.state.counter++;
|
||||||
@@ -16,13 +21,12 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
template = "Message";
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps !== this.props;
|
return nextProps !== this.props;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage() {
|
removeMessage() {
|
||||||
this.trigger("remove_message", {
|
this.trigger("remove_message", {
|
||||||
id: this.props.id
|
id: this.props.id
|
||||||
@@ -34,39 +38,123 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure('remove message');
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="'log'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
template = "Counter";
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
this.state.counter++;
|
this.state.counter++;
|
||||||
@@ -16,8 +21,8 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
template = "Message";
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps !== this.props;
|
return nextProps !== this.props;
|
||||||
@@ -33,39 +38,123 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="'log'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Counter extends owl.Component {
|
class Counter extends owl.Component {
|
||||||
template = "counter";
|
|
||||||
state = { counter: 0 };
|
state = { counter: 0 };
|
||||||
|
template = "Counter";
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
this.state.counter++;
|
this.state.counter++;
|
||||||
@@ -16,8 +21,8 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
template = "message";
|
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
template = "Message";
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps !== this.props;
|
return nextProps !== this.props;
|
||||||
@@ -33,39 +38,123 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
template = "root";
|
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
this.set(messages, i, msg);
|
this.set(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(data) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === data.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="root" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="'log'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" t-props="message" t-on-remove_message="removeMessage"/>
|
||||||
</t>
|
</t>
|
||||||
@@ -18,14 +36,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="message" class="message">
|
<div t-name="Message" class="message">
|
||||||
<span class="author"><t t-esc="props.author"/></span>
|
<span class="author"><t t-esc="props.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.msg"/></span>
|
<span class="msg"><t t-esc="props.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<t t-widget="Counter"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="counter">
|
<div t-name="Counter">
|
||||||
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
<button t-on-click="increment">Value: <t t-esc="state.counter"/></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Likes Counter Widget
|
// Likes Counter Widget
|
||||||
@@ -18,11 +23,11 @@ class Message extends owl.Component {
|
|||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps !== this.props;
|
return nextProps.message !== this.props.message;
|
||||||
}
|
}
|
||||||
removeMessage() {
|
removeMessage() {
|
||||||
this.trigger("remove_message", {
|
this.trigger("remove-message", {
|
||||||
id: this.props.id
|
id: this.props.message.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,38 +37,122 @@ class Message extends owl.Component {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = { Message };
|
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) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.state.messages.push.apply(this.state.messages, newMessages);
|
this.state.messages.push.apply(this.state.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.state.messages = [];
|
this.state.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const setState = owl.Observer.set;
|
const setState = owl.Observer.set;
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < this.state.messages.length; i += 10) {
|
for (let i = 0; i < this.state.messages.length; i += 10) {
|
||||||
const msg = Object.assign({}, messages[i]);
|
const msg = Object.assign({}, messages[i]);
|
||||||
msg.author += '!!!';
|
msg.author += "!!!";
|
||||||
setState(messages, i, msg);
|
setState(messages, i, msg);
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(data) {
|
removeMessage(event) {
|
||||||
startMeasure("remove message");
|
this.benchmark("remove message", () => {
|
||||||
const index = this.state.messages.findIndex(m => m.id === data.id);
|
const index = this.state.messages.findIndex(m => m.id === event.detail.id);
|
||||||
this.state.messages.splice(index, 1);
|
this.state.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.refs.log.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMultiple() {
|
||||||
|
this.state.multipleFlag = !this.state.multipleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleClear() {
|
||||||
|
this.state.clearAfterFlag = !this.state.clearAfterFlag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
<script src='../../owl.js'></script>
|
<script src='../../owl.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id='main'></div>
|
|
||||||
<script src='app.js' type="module"></script>
|
<script src='app.js' type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,18 +1,36 @@
|
|||||||
<templates>
|
<templates>
|
||||||
<div t-name="App" class="main">
|
<div t-name="App" class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: <t t-esc="state.messages.length"/></div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
<button t-on-click="addMessages(100)">Add 100 messages</button>
|
||||||
<button t-on-click="addMessages(1000)">Add 1000 messages</button>
|
<button t-on-click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button t-on-click="addMessages(10000)">Add 10000 messages</button>
|
<button t-on-click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button t-on-click="addMessages(50000)">Add 50000 messages</button>
|
<button t-on-click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button t-on-click="updateSomeMessages">Update every 10th message</button>
|
<button t-on-click="updateSomeMessages">Update every 10th messages</button>
|
||||||
<button t-on-click="clear">Clear</button>
|
<button t-on-click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" t-on-change="toggleMultiple" t-att-checked="state.multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" t-on-change="toggleClear" t-att-checked="state.clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: <t t-esc="state.messages.length"/></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" t-on-click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" t-ref="log"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" message="message" t-on-remove_message="removeMessage"/>
|
<t t-widget="Message" t-key="message.id" message="message"/>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+145
-21
@@ -1,4 +1,9 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Counter Widget
|
// Counter Widget
|
||||||
@@ -86,9 +91,33 @@ class Main extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
messages: []
|
messages: [],
|
||||||
|
multipleFlag: false,
|
||||||
|
clearAfterFlag: false
|
||||||
};
|
};
|
||||||
this.removeMessage = this.removeMessage.bind(this);
|
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() {
|
render() {
|
||||||
@@ -109,12 +138,10 @@ class Main extends React.Component {
|
|||||||
{
|
{
|
||||||
className: "left-thing"
|
className: "left-thing"
|
||||||
},
|
},
|
||||||
|
React.createElement("div", { className: "title" }, "Actions"),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"div",
|
"div",
|
||||||
null,
|
{ className: "panel" },
|
||||||
"Number of msg: ",
|
|
||||||
this.state.messages.length
|
|
||||||
),
|
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
@@ -127,28 +154,28 @@ class Main extends React.Component {
|
|||||||
{
|
{
|
||||||
onClick: _ => this.addMessages(1000)
|
onClick: _ => this.addMessages(1000)
|
||||||
},
|
},
|
||||||
"Add 1000 messages"
|
"Add 1k messages"
|
||||||
),
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
onClick: _ => this.addMessages(10000)
|
onClick: _ => this.addMessages(10000)
|
||||||
},
|
},
|
||||||
"Add 10000 messages"
|
"Add 10k messages"
|
||||||
),
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
onClick: _ => this.addMessages(50000)
|
onClick: _ => this.addMessages(30000)
|
||||||
},
|
},
|
||||||
"Add 50000 messages"
|
"Add 30k messages"
|
||||||
),
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
onClick: _ => this.updateSomeMessages()
|
onClick: _ => this.updateSomeMessages()
|
||||||
},
|
},
|
||||||
"Update every 10th messags"
|
"Update every 10th message"
|
||||||
),
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
@@ -158,6 +185,53 @@ class Main extends React.Component {
|
|||||||
"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(
|
||||||
|
"div",
|
||||||
|
{ className: "title" },
|
||||||
|
"Log ",
|
||||||
|
React.createElement("span", { className: "clear-log" }, "(clear)")
|
||||||
|
),
|
||||||
|
React.createElement(
|
||||||
|
"div",
|
||||||
|
{ className: "log" },
|
||||||
|
React.createElement("div", {
|
||||||
|
className: "log-content",
|
||||||
|
ref: "logref"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
@@ -175,30 +249,30 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMessages(n) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = this.state.messages.concat(buildData(n));
|
const newMessages = this.state.messages.concat(buildData(n));
|
||||||
this.setState({
|
this.setState({
|
||||||
messages: newMessages
|
messages: newMessages
|
||||||
});
|
});
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
messages: []
|
messages: []
|
||||||
});
|
});
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.state.messages;
|
const messages = this.state.messages;
|
||||||
for (let i = 0; i < messages.length; i += 10) {
|
for (let i = 0; i < messages.length; i += 10) {
|
||||||
messages[i].author += "!!!";
|
messages[i].author += "!!!";
|
||||||
}
|
}
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
stopMeasure();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(id) {
|
removeMessage(id) {
|
||||||
@@ -211,11 +285,61 @@ class Main extends React.Component {
|
|||||||
});
|
});
|
||||||
stopMeasure();
|
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
|
// INIT
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(React.createElement(Main, null), document.body);
|
||||||
React.createElement(Main, null),
|
|
||||||
document.getElementById("main")
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,26 +1,91 @@
|
|||||||
.main {
|
html,
|
||||||
position: absolute;
|
body {
|
||||||
left: 0;
|
height: 100%;
|
||||||
right: 0;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
top: 0;
|
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial,
|
||||||
bottom: 0;
|
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
font-size: 14px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 220px 1fr;
|
grid-template-columns: 640px 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-thing {
|
.left-thing {
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
padding: 20px;
|
|
||||||
color: white;
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-thing button {
|
.left-thing hr {
|
||||||
width: 100%;
|
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 {
|
.right-thing {
|
||||||
padding: 20px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,19 +31,28 @@ export function buildData(n = 1000) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Measuring helpers
|
// Measuring helpers
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
export function formatNumber(n) {
|
||||||
|
return Number(n).toFixed();
|
||||||
|
}
|
||||||
|
|
||||||
let startTime;
|
let startTime;
|
||||||
let lastMeasure;
|
let lastMeasure;
|
||||||
export function startMeasure(descr) {
|
export function startMeasure(descr) {
|
||||||
startTime = performance.now();
|
startTime = performance.now();
|
||||||
lastMeasure = descr;
|
lastMeasure = descr;
|
||||||
}
|
}
|
||||||
export function stopMeasure() {
|
export function stopMeasure(cb) {
|
||||||
let last = lastMeasure;
|
let last = lastMeasure;
|
||||||
if (lastMeasure) {
|
if (lastMeasure) {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
lastMeasure = null;
|
lastMeasure = null;
|
||||||
const stop = performance.now();
|
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);
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+104
-12
@@ -1,4 +1,9 @@
|
|||||||
import { buildData, startMeasure, stopMeasure } from "../shared/utils.js";
|
import {
|
||||||
|
buildData,
|
||||||
|
startMeasure,
|
||||||
|
stopMeasure,
|
||||||
|
formatNumber
|
||||||
|
} from "../shared/utils.js";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Counter Widget
|
// Counter Widget
|
||||||
@@ -45,29 +50,36 @@ Vue.component("my-message", {
|
|||||||
const App = {
|
const App = {
|
||||||
name: "App",
|
name: "App",
|
||||||
data() {
|
data() {
|
||||||
return { messages: [] };
|
return { messages: [], multipleFlag: false, clearAfterFlag: false };
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.log(`Benchmarking Vue v${Vue.version}`);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addMessages(n) {
|
addMessages(n) {
|
||||||
startMeasure("add " + n);
|
this.benchmark("add " + n, () => {
|
||||||
const newMessages = buildData(n);
|
const newMessages = buildData(n);
|
||||||
this.messages.push.apply(this.messages, newMessages);
|
this.messages.push.apply(this.messages, newMessages);
|
||||||
stopMeasure();
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
startMeasure("clear");
|
this._benchmark("clear", () => {
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
stopMeasure();
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
clearLog() {
|
||||||
|
this.$refs.log.innerHTML = "";
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSomeMessages() {
|
updateSomeMessages() {
|
||||||
startMeasure("update every 10th");
|
this.benchmark("update every 10th", () => {
|
||||||
const messages = this.messages;
|
const messages = this.messages;
|
||||||
for (let i = 0; i < this.messages.length; i += 10) {
|
for (let i = 0; i < this.messages.length; i += 10) {
|
||||||
messages[i].author += "!!!";
|
messages[i].author += "!!!";
|
||||||
}
|
}
|
||||||
stopMeasure();
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeMessage(id) {
|
removeMessage(id) {
|
||||||
@@ -75,19 +87,99 @@ const App = {
|
|||||||
const index = this.messages.findIndex(m => m.id === id);
|
const index = this.messages.findIndex(m => m.id === id);
|
||||||
this.messages.splice(index, 1);
|
this.messages.splice(index, 1);
|
||||||
stopMeasure();
|
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: `
|
template: `
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="left-thing">
|
<div class="left-thing">
|
||||||
<div>Number of msg: {{messages.length}}</div>
|
<div class="title">Actions</div>
|
||||||
|
<div class="panel">
|
||||||
<button @click="addMessages(100)">Add 100 messages</button>
|
<button @click="addMessages(100)">Add 100 messages</button>
|
||||||
<button @click="addMessages(1000)">Add 1000 messages</button>
|
<button @click="addMessages(1000)">Add 1k messages</button>
|
||||||
<button @click="addMessages(10000)">Add 10000 messages</button>
|
<button @click="addMessages(10000)">Add 10k messages</button>
|
||||||
<button @click="addMessages(50000)">Add 50000 messages</button>
|
<button @click="addMessages(30000)">Add 30k messages</button>
|
||||||
<button @click="updateSomeMessages">Update every 10th message</button>
|
<button @click="updateSomeMessages">Update every 10th message</button>
|
||||||
<button @click="clear">Clear</button>
|
<button @click="clear">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multipleflag" v-model="multipleFlag"/>
|
||||||
|
<label for="multipleflag">Do it 20x</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="clearFlag" v-model="clearAfterFlag"/>
|
||||||
|
<label for="clearFlag">Clear after</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">Number of messages: {{messages.length}}</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="title">Log <span class="clear-log" @click="clearLog">(clear)</span></div>
|
||||||
|
<div class="log">
|
||||||
|
<div class="log-content" ref="log"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<my-message v-for="msg in messages" v-bind:key="msg.id" v-bind:msg="msg" @removeMessage="removeMessage"></my-message>
|
<my-message v-for="msg in messages" v-bind:key="msg.id" v-bind:msg="msg" @removeMessage="removeMessage"></my-message>
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>OWL Extras</title>
|
<title>OWL Tools</title>
|
||||||
<link rel="stylesheet" href="main.css">
|
<link rel="stylesheet" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
+5
-1
@@ -1,5 +1,9 @@
|
|||||||
|
html,
|
||||||
body {
|
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,
|
.title,
|
||||||
|
|||||||
Reference in New Issue
Block a user