Skip to content

Commit cec22a9

Browse files
authored
perf: Optimize widget performance with Set lookups and RAF throttling (#5458)
- Convert Array.includes() to Set.has() for O(1) lookups in musickeyboard.js (2 locations) - Convert Array.includes() to Set.has() in rhythmruler.js saveDissectHistory (2 locations) - Add requestAnimationFrame throttle to widgetWindows.js mousemove handler
1 parent b220726 commit cec22a9

File tree

3 files changed

+57
-44
lines changed

3 files changed

+57
-44
lines changed

js/widgets/musickeyboard.js

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,15 +1263,17 @@ function MusicKeyboard(activity) {
12631263
return a.frequency - b.frequency;
12641264
});
12651265

1266-
const unique = [];
1266+
// Use Set for O(1) lookup instead of Array.includes() O(n)
1267+
const unique = new Set();
12671268
this.remove = [];
12681269

12691270
sortedList = sortedList.filter(item => {
1270-
if (!unique.includes(item.noteName + item.noteOctave)) {
1271-
unique.push(item.noteName + item.noteOctave);
1271+
const key = item.noteName + item.noteOctave;
1272+
if (!unique.has(key)) {
1273+
unique.add(key);
12721274
return true;
12731275
} else if (item.noteName === "drum") {
1274-
unique.push(item.noteName + item.noteOctave);
1276+
unique.add(key);
12751277
return true;
12761278
}
12771279

@@ -1812,18 +1814,16 @@ function MusicKeyboard(activity) {
18121814
this._menuWheel.navItems[3].navigateFunction = () => {
18131815
if (!flag) {
18141816
for (let i = 12; i < 19; i++) {
1815-
docById(
1816-
"wheelnav-wheelDivptm-title-3"
1817-
).children[0].textContent = this.newNoteValue;
1817+
docById("wheelnav-wheelDivptm-title-3").children[0].textContent =
1818+
this.newNoteValue;
18181819
this._tabsWheel.navItems[i].navItem.show();
18191820
}
18201821

18211822
flag = 1;
18221823
} else {
18231824
for (let i = 12; i < 19; i++) {
1824-
docById(
1825-
"wheelnav-wheelDivptm-title-3"
1826-
).children[0].textContent = this.newNoteValue;
1825+
docById("wheelnav-wheelDivptm-title-3").children[0].textContent =
1826+
this.newNoteValue;
18271827
this._tabsWheel.navItems[i].navItem.hide();
18281828
}
18291829

@@ -2254,11 +2254,13 @@ function MusicKeyboard(activity) {
22542254
return aValue - bValue;
22552255
});
22562256

2257-
const unique = [];
2257+
// Use Set for O(1) lookup instead of Array.includes() O(n)
2258+
const unique = new Set();
22582259
this.remove = [];
22592260
this.layout = this.layout.filter((item, pos) => {
2260-
if (!unique.includes(item.noteName + item.noteOctave)) {
2261-
unique.push(item.noteName + item.noteOctave);
2261+
const key = item.noteName + item.noteOctave;
2262+
if (!unique.has(key)) {
2263+
unique.add(key);
22622264
return true;
22632265
}
22642266

@@ -2465,14 +2467,14 @@ function MusicKeyboard(activity) {
24652467
index = this.layout.length - index - 1;
24662468
const block = this.layout[index].blockNumber;
24672469

2468-
let noteValue = this.activity.blocks.blockList[
2469-
this.activity.blocks.blockList[block].connections[1]
2470-
].value;
2470+
let noteValue =
2471+
this.activity.blocks.blockList[this.activity.blocks.blockList[block].connections[1]]
2472+
.value;
24712473

24722474
if (condition === "pitchblocks") {
2473-
const octaveValue = this.activity.blocks.blockList[
2474-
this.activity.blocks.blockList[block].connections[2]
2475-
].value;
2475+
const octaveValue =
2476+
this.activity.blocks.blockList[this.activity.blocks.blockList[block].connections[2]]
2477+
.value;
24762478
let accidentalsValue = 2;
24772479

24782480
for (let i = 0; i < accidentals.length; i++) {
@@ -2503,8 +2505,8 @@ function MusicKeyboard(activity) {
25032505
* Handles the hertz selection change for the pitch wheel.
25042506
*/
25052507
const __hertzSelectionChanged = () => {
2506-
const blockValue = this._pitchWheel.navItems[this._pitchWheel.selectedNavItemIndex]
2507-
.title;
2508+
const blockValue =
2509+
this._pitchWheel.navItems[this._pitchWheel.selectedNavItemIndex].title;
25082510
const argBlock = this.activity.blocks.blockList[block].connections[1];
25092511
this.activity.blocks.blockList[argBlock].text.text = blockValue;
25102512
this.activity.blocks.blockList[argBlock].value = parseInt(blockValue);
@@ -2543,8 +2545,9 @@ function MusicKeyboard(activity) {
25432545
if (condition === "pitchblocks") {
25442546
i = noteLabelsI18n.indexOf(label);
25452547
labelValue = noteLabels[i];
2546-
attr = this._accidentalsWheel.navItems[this._accidentalsWheel.selectedNavItemIndex]
2547-
.title;
2548+
attr =
2549+
this._accidentalsWheel.navItems[this._accidentalsWheel.selectedNavItemIndex]
2550+
.title;
25482551
if (attr !== "♮") {
25492552
label += attr;
25502553
}
@@ -2605,9 +2608,8 @@ function MusicKeyboard(activity) {
26052608
const i = noteLabelsI18n.indexOf(label);
26062609
let labelValue = noteLabels[i];
26072610

2608-
const attr = this._accidentalsWheel.navItems[
2609-
this._accidentalsWheel.selectedNavItemIndex
2610-
].title;
2611+
const attr =
2612+
this._accidentalsWheel.navItems[this._accidentalsWheel.selectedNavItemIndex].title;
26112613
if (attr !== "♮") {
26122614
labelValue += attr;
26132615
}
@@ -3223,10 +3225,9 @@ function MusicKeyboard(activity) {
32233225
[
32243226
"number",
32253227
{
3226-
value:
3227-
note.noteOctave[j][
3228-
note.noteOctave[j].length - 1
3229-
]
3228+
value: note.noteOctave[j][
3229+
note.noteOctave[j].length - 1
3230+
]
32303231
}
32313232
],
32323233
0,
@@ -3251,10 +3252,9 @@ function MusicKeyboard(activity) {
32513252
[
32523253
"number",
32533254
{
3254-
value:
3255-
note.noteOctave[j][
3256-
note.noteOctave[j].length - 1
3257-
]
3255+
value: note.noteOctave[j][
3256+
note.noteOctave[j].length - 1
3257+
]
32583258
}
32593259
],
32603260
0,

js/widgets/rhythmruler.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,11 @@ class RhythmRuler {
420420
}
421421

422422
// Look for any old entries that we may have missed.
423+
// Use Set for O(1) lookup instead of Array.includes() O(n)
424+
const drumsSet = new Set(drums);
423425
for (let i = 0; i < this._dissectHistory.length; i++) {
424426
const drum = this._dissectHistory[i][1];
425-
if (!drums.includes(drum)) {
427+
if (!drumsSet.has(drum)) {
426428
const history = JSON.parse(JSON.stringify(this._dissectHistory[i][0]));
427429
dissectHistory.push([history, drum]);
428430
}
@@ -2723,9 +2725,11 @@ class RhythmRuler {
27232725
}
27242726

27252727
// Look for any old entries that we may have missed.
2728+
// Use Set for O(1) lookup instead of Array.includes() O(n)
2729+
const drumsSet = new Set(drums);
27262730
for (let i = 0; i < this._dissectHistory.length; i++) {
27272731
drum = this._dissectHistory[i][1];
2728-
if (!drums.includes(drum)) {
2732+
if (!drumsSet.has(drum)) {
27292733
history = JSON.parse(JSON.stringify(this._dissectHistory[i][0]));
27302734
dissectHistory.push([history, drum]);
27312735
}

js/widgets/widgetWindows.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class WidgetWindow {
4040
// Drag offset for correct positioning
4141
this._dx = this._dy = 0;
4242
this._dragging = false;
43+
// RAF throttle flag for mousemove performance
44+
this._rafTicking = false;
4345

4446
this._createUIelements();
4547
this._setupLanguage();
@@ -212,15 +214,22 @@ class WidgetWindow {
212214
_docMouseMoveHandler(e) {
213215
if (!this._dragging) return;
214216

215-
if (this._fullscreenEnabled && this._frame.style.top === "64px") {
216-
this._overlay(true);
217-
} else {
218-
this._overlay(false);
219-
}
220-
const x = e.clientX - this._dx,
221-
y = e.clientY - this._dy;
217+
// Throttle using requestAnimationFrame to prevent layout thrashing
218+
if (this._rafTicking) return;
219+
this._rafTicking = true;
220+
221+
requestAnimationFrame(() => {
222+
if (this._fullscreenEnabled && this._frame.style.top === "64px") {
223+
this._overlay(true);
224+
} else {
225+
this._overlay(false);
226+
}
227+
const x = e.clientX - this._dx,
228+
y = e.clientY - this._dy;
222229

223-
this.setPosition(x, y);
230+
this.setPosition(x, y);
231+
this._rafTicking = false;
232+
});
224233
}
225234

226235
_overlay(add) {

0 commit comments

Comments
 (0)