Skip to content

Commit 0c4eca8

Browse files
Merge pull request #580 from lukecotter/perf-calltree-render
bug(perf): regression in call tree render performance
2 parents d33e705 + 33fe5be commit 0c4eca8

6 files changed

Lines changed: 71 additions & 62 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Highlight and copy text to clipboard: Call Tree, Analysis and Database views ([#504][#504])
1313
- Previously the highlighted text would be immediately cleared
1414

15+
### Fixed
16+
17+
- Performance regression of Call Tree rendering ([#581][#581])
18+
- Call Tree not correctly keeping position when rows where hidden / shown via Details and Debug Only ([#581][#581])
19+
1520
## [1.16.1] - 2024-12-03
1621

1722
### Fixed
@@ -369,6 +374,7 @@ Skipped due to adopting odd numbering for pre releases and even number for relea
369374
<!-- Unreleased -->
370375

371376
[#504]: https://github.com/certinia/debug-log-analyzer/issues/504
377+
[#581]: https://github.com/certinia/debug-log-analyzer/issues/581
372378

373379
<!-- 1.16.1 -->
374380

log-viewer/modules/components/calltree-view/CalltreeView.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,7 @@ export class CalltreeView extends LitElement {
571571
}
572572
},
573573
rowFormatter: (row: RowComponent) => {
574-
requestAnimationFrame(() => {
575-
formatter(row, this.findArgs);
576-
});
574+
formatter(row, this.findArgs);
577575
},
578576
columnCalcs: 'both',
579577
columnDefaults: {

log-viewer/modules/components/calltree-view/module/Find.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -157,25 +157,27 @@ export class Find extends Module {
157157
}
158158

159159
export function formatter(row: RowComponent, findArgs: FindArgs) {
160-
if (!findArgs.text || !row.getData()) {
160+
const { text, count } = findArgs;
161+
if (!text || !count || !row.getData()) {
161162
return;
162163
}
164+
requestAnimationFrame(() => {
165+
const data = row.getData();
166+
const highlights = {
167+
indexes: data.highlightIndexes,
168+
currentMatch: 0,
169+
};
163170

164-
const data = row.getData();
165-
const highlights = {
166-
indexes: data.highlightIndexes,
167-
currentMatch: 0,
168-
};
171+
row.getCells().forEach((cell) => {
172+
const cellElem = cell.getElement();
173+
_highlightText(cellElem, findArgs, highlights);
174+
});
169175

170-
row.getCells().forEach((cell) => {
171-
const cellElem = cell.getElement();
172-
_highlightText(cellElem, findArgs, highlights);
176+
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
177+
if (row._getSelf().type === 'row') {
178+
row.normalizeHeight();
179+
}
173180
});
174-
175-
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
176-
if (row._getSelf().type === 'row') {
177-
row.normalizeHeight();
178-
}
179181
}
180182

181183
function _highlightText(

log-viewer/modules/components/calltree-view/module/MiddleRowFocus.ts

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const middleRowFocusOption = 'middleRowFocus' as const;
1616
export class MiddleRowFocus extends Module {
1717
static moduleName = 'middleRowFocus';
1818

19-
goToRowId: number = 0;
19+
tableHolder: HTMLElement | null = null;
20+
middleRow: RowComponent | null = null;
2021
constructor(table: Tabulator) {
2122
super(table);
2223
this.registerTableOption(middleRowFocusOption, false);
@@ -25,60 +26,64 @@ export class MiddleRowFocus extends Module {
2526
initialize() {
2627
// @ts-expect-error not in types
2728
if (this.options(middleRowFocusOption)) {
29+
this.tableHolder = this.table.element.querySelector('.tabulator-tableholder');
30+
2831
this.table.on('dataTreeRowExpanded', () => {
29-
window.clearTimeout(this.goToRowId);
30-
middleRow = null;
32+
this._clearFocusRow();
3133
});
3234

3335
this.table.on('dataTreeRowCollapsed', () => {
34-
window.clearTimeout(this.goToRowId);
35-
middleRow = null;
36+
this._clearFocusRow();
3637
});
3738

38-
let middleRow: RowComponent | null;
3939
this.table.on('renderStarted', () => {
40-
if (this.table && !middleRow) {
41-
middleRow = this._findMiddleVisibleRow(this.table);
40+
if (this.table && this.tableHolder && !this.middleRow) {
41+
this.middleRow = this._findMiddleVisibleRow(this.tableHolder);
4242
}
4343
});
4444

4545
this.table.on('renderComplete', async () => {
46-
const rowToScrollTo = middleRow;
47-
this.goToRowId = this._scrollToRow(rowToScrollTo);
48-
middleRow = null;
46+
const rowToScrollTo = this.middleRow;
47+
this._scrollToRow(rowToScrollTo);
48+
this.middleRow = null;
4949
});
5050
}
5151
}
5252

53-
private _scrollToRow(row: RowComponent | null): number {
53+
private _clearFocusRow() {
54+
this.middleRow = null;
55+
}
56+
57+
private _scrollToRow(row: RowComponent | null) {
5458
if (!row) {
55-
return 0;
59+
return;
5660
}
57-
return window.setTimeout(() => {
58-
let rowToScrollTo: RowComponent | null = row;
59-
if (rowToScrollTo) {
60-
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
61-
const internalRow = rowToScrollTo._getSelf();
62-
const displayRows = internalRow.table.rowManager.getDisplayRows();
63-
const canScroll = displayRows.indexOf(internalRow) !== -1;
64-
if (!canScroll) {
65-
const rowData = rowToScrollTo.getData() as TimedNodeProp;
66-
const node = rowData.originalData;
67-
68-
rowToScrollTo = this._findClosestActive(this.table.getRows('active'), node.timestamp);
69-
}
7061

71-
if (rowToScrollTo) {
72-
this.table.scrollToRow(rowToScrollTo, 'center', true).then(() => {
62+
let rowToScrollTo: RowComponent | null = row;
63+
if (rowToScrollTo) {
64+
const displayRows = this.table.rowManager.getDisplayRows();
65+
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
66+
const internalRow = rowToScrollTo._getSelf();
67+
const canScroll = displayRows.indexOf(internalRow) !== -1;
68+
if (!canScroll) {
69+
const rowData = rowToScrollTo.getData() as TimedNodeProp;
70+
const node = rowData.originalData;
71+
72+
rowToScrollTo = this._findClosestActive(this.table.getRows('active'), node.timestamp);
73+
}
74+
75+
if (rowToScrollTo) {
76+
this.table.scrollToRow(rowToScrollTo, 'center', true).then(() => {
77+
setTimeout(() => {
7378
if (rowToScrollTo) {
7479
rowToScrollTo
7580
?.getElement()
7681
.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' });
7782
}
7883
});
79-
}
84+
});
8085
}
81-
});
86+
}
8287
}
8388

8489
private _findClosestActive(rows: RowComponent[], timeStamp: number): RowComponent | null {
@@ -90,6 +95,7 @@ export class MiddleRowFocus extends Module {
9095
end = rows.length - 1;
9196

9297
// Iterate as long as the beginning does not encounter the end.
98+
const displayRows = this.table.rowManager.getDisplayRows();
9399
while (start <= end) {
94100
// find out the middle index
95101
const mid = Math.floor((start + end) / 2);
@@ -99,13 +105,11 @@ export class MiddleRowFocus extends Module {
99105
break;
100106
}
101107
const node = (row.getData() as TimedNodeProp).originalData;
102-
103-
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
104-
const internalRow = row._getSelf();
105-
const displayRows = internalRow.table.rowManager.getDisplayRows();
106108
const endTime = node.exitStamp ?? node.timestamp;
107109

108110
if (timeStamp === node.timestamp) {
111+
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
112+
const internalRow = row._getSelf();
109113
const isActive = displayRows.indexOf(internalRow) !== -1;
110114
if (isActive) {
111115
return row;
@@ -187,13 +191,16 @@ export class MiddleRowFocus extends Module {
187191
return closestIndex ? rows[closestIndex] || null : null;
188192
}
189193

190-
private _findMiddleVisibleRow(table: Tabulator) {
191-
const visibleRows = table.getRows('visible');
192-
if (visibleRows.length === 1) {
193-
return visibleRows[0] || null;
194+
private _findMiddleVisibleRow(tableHolder: HTMLElement) {
195+
const visibleRows = this.table.getRows('visible');
196+
const len = visibleRows.length;
197+
if (len === 0) {
198+
return null;
199+
} else if (len === 1) {
200+
return visibleRows[0] ?? null;
194201
}
195202

196-
const tableRect = table.element.getBoundingClientRect();
203+
const tableRect = tableHolder.getBoundingClientRect();
197204
const totalHeight = Math.round(tableRect.height / 2);
198205

199206
let currentHeight = 0;

log-viewer/modules/components/database-view/DMLView.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,7 @@ export class DMLView extends LitElement {
338338
row.normalizeHeight();
339339
}
340340

341-
requestAnimationFrame(() => {
342-
formatter(row, this.findArgs);
343-
});
341+
formatter(row, this.findArgs);
344342
},
345343
});
346344

log-viewer/modules/components/database-view/SOQLView.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,7 @@ export class SOQLView extends LitElement {
477477
row.normalizeHeight();
478478
}
479479

480-
requestAnimationFrame(() => {
481-
formatter(row, this.findArgs);
482-
});
480+
formatter(row, this.findArgs);
483481
},
484482
});
485483

0 commit comments

Comments
 (0)