From 3d9c2ae507575591956c42aede97a513197c7840 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Sun, 22 Mar 2026 01:32:21 +0800 Subject: [PATCH] perf(website): cache sort values and batch DOM appends in sortRows Calling getSortValue inside the comparator ran DOM queries on every comparison (O(n log n) reads). Hoisting into a forEach beforehand reduces that to O(n). Batching row appends through a DocumentFragment also avoids repeated reflows during table reorder. Co-Authored-By: Claude --- website/static/main.js | 49 ++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/website/static/main.js b/website/static/main.js index 9c7b159..7168986 100644 --- a/website/static/main.js +++ b/website/static/main.js @@ -143,29 +143,36 @@ function getSortValue(row, col) { function sortRows() { var arr = Array.prototype.slice.call(rows); - if (activeSort) { - arr.sort(function (a, b) { - var aVal = getSortValue(a, activeSort.col); - var bVal = getSortValue(b, activeSort.col); - if (activeSort.col === 'name') { - var cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0; - if (cmp === 0) return a._origIndex - b._origIndex; - return activeSort.order === 'desc' ? -cmp : cmp; - } - if (aVal <= 0 && bVal <= 0) return a._origIndex - b._origIndex; - if (aVal <= 0) return 1; - if (bVal <= 0) return -1; - var cmp = aVal - bVal; - if (cmp === 0) return a._origIndex - b._origIndex; - return activeSort.order === 'desc' ? -cmp : cmp; - }); - } else { - arr.sort(function (a, b) { return a._origIndex - b._origIndex; }); - } + var col = activeSort.col; + var order = activeSort.order; + + // Cache sort values once to avoid DOM queries per comparison arr.forEach(function (row) { - tbody.appendChild(row); - tbody.appendChild(row._expandRow); + row._sortVal = getSortValue(row, col); }); + + arr.sort(function (a, b) { + var aVal = a._sortVal; + var bVal = b._sortVal; + if (col === 'name') { + var cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0; + if (cmp === 0) return a._origIndex - b._origIndex; + return order === 'desc' ? -cmp : cmp; + } + if (aVal <= 0 && bVal <= 0) return a._origIndex - b._origIndex; + if (aVal <= 0) return 1; + if (bVal <= 0) return -1; + var cmp = aVal - bVal; + if (cmp === 0) return a._origIndex - b._origIndex; + return order === 'desc' ? -cmp : cmp; + }); + + var frag = document.createDocumentFragment(); + arr.forEach(function (row) { + frag.appendChild(row); + frag.appendChild(row._expandRow); + }); + tbody.appendChild(frag); applyFilters(); }