diff/patch slower in 10.4.5 when removing >1 keyed items from the list
See original GitHub issueLooks like the diff/patch sometimes does unnecessary re-ordering of the child nodes instead of just remove two or more consecutive items from the middle of the list. Removing 1 item is OK. The version 10.4.4 was OK - issue started in 10.4.5.
We make a datagrid component which implements virtualized scrollling (i.e. adding/removing rows on the fly) and this issue totally kills the performance - i.e. full component repaint instead of just the affected rows.
Reproduction
Here is the static html page to reproduce the issue -
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/preact@10.4.5/dist/preact.umd.js"></script>
<script src="https://unpkg.com/@activewidgets/examples@0.0.10/data/index.common.js"></script>
<script src="https://cdn.activewidgets.com/preact@3.0.4/bundle.js"></script>
<style>
body { font: 14px/1.2143 'Segoe UI', 'Avenir', 'Helvetica Neue', 'Tahoma', sans-serif;}
.ax-headers-view { font-weight: bold; color: #666; border-bottom: 1px solid #aaa;}
</style>
</head>
<body>
<div id="app"></div>
<script type="module">
let {h, render} = preact,
{Datagrid} = ActiveWidgets.Preact;
let el = document.getElementById('app'),
app = h(Datagrid, {rows, columns});
render(app, el);
// --------------------------------------------
let observer = new MutationObserver(mutations => {
if (mutations.length > 50){
console.log('!!!'); // put breakpoint here
}
function rows(rec){
return rec.type == 'childList' && rec.target.className.indexOf('fixed') > 0;
}
function out(rec){
let s = '';
rec.addedNodes.forEach(n => {
s += 'add ' + n.children[0].children[0].innerText;
});
rec.removedNodes.forEach(n => {
s += 'remove ' + n.children[0].children[0].innerText;
});
return s;
}
console.log(mutations.filter(rows).map(out));
});
observer.observe(el, {childList: true, subtree: true});
</script>
</body>
</html>
Steps to reproduce
Open the browser developer tools console and then slowly scroll the datagrid down either with mousewheel or scrollbar. The console should show added/removed rows, like
["add GROSR"]
["remove AROUT"]
["add HANAR"]
["remove BERGS"]
["add HILAA"]
["remove BLAUS"]
Scroll faster - as soon as you scroll more than 2 rows per 0.1s you will see something like this -
["remove BONAP", "add BONAP", "remove BOTTM", "add BOTTM", "remove BSBEV", "add BSBEV", "remove CACTU", "add CACTU", "remove CENTC", "add CENTC", "remove CHOPS", "add CHOPS", "remove COMMI", "add COMMI", "remove CONSH", "add CONSH", "remove DRACD", "add DRACD", "remove DUMON", "add DUMON", "remove EASTC", "add EASTC", "remove ERNSH", "add ERNSH", "remove FAMIA", "add FAMIA", "remove FISSA", "add FISSA", "remove FOLIG", "add FOLIG", "remove FOLKO", "add FOLKO", "remove FRANK", "add FRANK", "remove FRANR", "add FRANR", "remove FRANS", "add FRANS", "remove FURIB", "add FURIB", "remove GALED", "add GALED", "remove GODOS", "add GODOS", "remove GOURL", "add GOURL", "remove GREAL", "add GREAL", "remove GROSR", "add GROSR", "remove HANAR", "add HANAR", "remove HILAA", "add HILAA", "remove HUNGC", "add HUNGC", "remove HUNGO", "add HUNGO", "remove BOLID", "remove BLONP"]
Expected Behavior
If you replace 10.4.5 with 10.4.4 then adding/removing rows works as expected, including more than 1 row at a time -
["add FAMIA", "add FISSA", "add FOLIG"]
["add FOLKO", "add FRANK", "add FRANR", "add FRANS"]
["add FURIB", "add GALED", "add GODOS", "add GOURL"]
["remove ANATR", "remove ALFKI"]
["add GREAL", "add GROSR", "add HANAR", "add HILAA", "add HUNGC"]
["remove BLONP", "remove BLAUS", "remove BERGS", "remove AROUT", "remove ANTON"]
["add HUNGO", "add ISLAT", "add KOENE", "add LACOR"]
["remove BSBEV", "remove BOTTM", "remove BONAP", "remove BOLID"]
["add LAMAI", "add LAUGB", "add LAZYK", "add LEHMS", "add LETSS"]
["remove COMMI", "remove CHOPS", "remove CENTC", "remove CACTU"]
["add LILAS", "add LINOD", "add LONEP"]
["remove EASTC", "remove DUMON", "remove DRACD", "remove CONSH"]
Tested with Chrome 83.0.4103.116 and Firefox 77.0.1
Issue Analytics
- State:
- Created 3 years ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
Moved to https://github.com/preactjs/preact/issues/2622
Just want to clarify that performance impact is not that js execution is taking more time, but that it triggers DOM style/layout/repaint (for 1000s of elements in our case) where previously there was none.