During the Knockout upgrade process for version 4.0 (now in monorepo tko mode), I ran into some performance issues.
Among other changes, some things inside the loop were converted to ES6 classes and caused some serious performance issues. I would prefer not to undo this effort, as it adds some clarity to some key code, so I would like to ask for some information on how to improve ES6 code.
I created some simple profiling examples here:
The code in jsFiddles is as follows, and it prototypes the slowdown experienced by many bindings.
HTML:
<div id='x'> <strong>{{ count }} / {{ time }} ms</strong> <custom-component></custom-component> </div> <div id='cc-template'> cc {{# unless: finished }} <custom-component></custom-component> {{ /unless }} </div>
JavaScript:
let count = ko.observable(0) let time = ko.observable(false) const start = performance.now() const ITERATIONS = 1000 class viewModel { constructor () { this.finished = count() > ITERATIONS count(count() + 1) time(performance.now() - start) } } ko.components.register("custom-component", { viewModel, template: {element: 'cc-template'} }) ko.applyBindings({count, time}, document.getElementById('x'))
If you are comparing Javascript profiles, call trees are almost identical (despite ES6 changes). It seems that the extra time in Alpha3 is on leaf calls, which makes it difficult to identify them, so I assume that based on profile mappings, the problem is several times, including:
- some non-optimization or de-optimization occurs
- some loops are replaced by slower, native calls, for example.
Array.from - smaller garbage collectors
- less built-in optimization for ES6isms
In any case, I am not rooted, which, if any of them, is still a problem, or where exactly they may arise.
I would be very grateful for your understanding and help to determine where we can do the optimization in order to return performance or even higher.
Brian M. hunt
source share