Skip to content

Commit 801461e

Browse files
committed
Re-use profiler visualization for extra networks
1 parent eee46a5 commit 801461e

File tree

3 files changed

+178
-93
lines changed

3 files changed

+178
-93
lines changed

.eslintrc.js

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ module.exports = {
7878
//extraNetworks.js
7979
requestGet: "readonly",
8080
popup: "readonly",
81+
// profilerVisualization.js
82+
createVisualizationTable: "readonly",
8183
// from python
8284
localization: "readonly",
8385
// progrssbar.js

javascript/extraNetworks.js

+62
Original file line numberDiff line numberDiff line change
@@ -528,12 +528,74 @@ function popupId(id) {
528528
popup(storedPopupIds[id]);
529529
}
530530

531+
function extraNetworksFlattenMetadata(obj) {
532+
const result = {};
533+
534+
// Convert any stringified JSON objects to actual objects
535+
for (const key of Object.keys(obj)) {
536+
if (typeof obj[key] === 'string') {
537+
try {
538+
const parsed = JSON.parse(obj[key]);
539+
if (parsed && typeof parsed === 'object') {
540+
obj[key] = parsed;
541+
}
542+
} catch (error) {
543+
continue;
544+
}
545+
}
546+
}
547+
548+
// Flatten the object
549+
for (const key of Object.keys(obj)) {
550+
if (typeof obj[key] === 'object' && obj[key] !== null) {
551+
const nested = extraNetworksFlattenMetadata(obj[key]);
552+
for (const nestedKey of Object.keys(nested)) {
553+
result[`${key}/${nestedKey}`] = nested[nestedKey];
554+
}
555+
} else {
556+
result[key] = obj[key];
557+
}
558+
}
559+
560+
// Special case for handling modelspec keys
561+
for (const key of Object.keys(result)) {
562+
if (key.startsWith("modelspec.")) {
563+
result[key.replaceAll(".", "/")] = result[key];
564+
delete result[key];
565+
}
566+
}
567+
568+
// Add empty keys to designate hierarchy
569+
for (const key of Object.keys(result)) {
570+
const parts = key.split("/");
571+
for (let i = 1; i < parts.length; i++) {
572+
const parent = parts.slice(0, i).join("/");
573+
if (!result[parent]) {
574+
result[parent] = "";
575+
}
576+
}
577+
}
578+
579+
return result;
580+
}
581+
531582
function extraNetworksShowMetadata(text) {
583+
try {
584+
let parsed = JSON.parse(text);
585+
if (parsed && typeof parsed === 'object') {
586+
parsed = extraNetworksFlattenMetadata(parsed);
587+
const table = createVisualizationTable(parsed, 0);
588+
popup(table);
589+
return;
590+
}
591+
} catch (error) { console.debug(error); }
592+
532593
var elem = document.createElement('pre');
533594
elem.classList.add('popup-metadata');
534595
elem.textContent = text;
535596

536597
popup(elem);
598+
return;
537599
}
538600

539601
function requestGet(url, data, handler, errorHandler) {

javascript/profilerVisualization.js

+114-93
Original file line numberDiff line numberDiff line change
@@ -33,120 +33,141 @@ function createRow(table, cellName, items) {
3333
return res;
3434
}
3535

36-
function showProfile(path, cutoff = 0.05) {
37-
requestGet(path, {}, function(data) {
38-
var table = document.createElement('table');
39-
table.className = 'popup-table';
40-
41-
data.records['total'] = data.total;
42-
var keys = Object.keys(data.records).sort(function(a, b) {
43-
return data.records[b] - data.records[a];
36+
function createVisualizationTable(data, cutoff = 0, sort = "") {
37+
var table = document.createElement('table');
38+
table.className = 'popup-table';
39+
40+
var keys = Object.keys(data);
41+
if (sort === "number") {
42+
keys = keys.sort(function(a, b) {
43+
return data[b] - data[a];
4444
});
45-
var items = keys.map(function(x) {
46-
return {key: x, parts: x.split('/'), time: data.records[x]};
45+
} else {
46+
keys = keys.sort();
47+
}
48+
var items = keys.map(function(x) {
49+
return {key: x, parts: x.split('/'), value: data[x]};
50+
});
51+
var maxLength = items.reduce(function(a, b) {
52+
return Math.max(a, b.parts.length);
53+
}, 0);
54+
55+
var cols = createRow(
56+
table,
57+
'th',
58+
[
59+
cutoff === 0 ? 'key' : 'record',
60+
cutoff === 0 ? 'value' : 'seconds'
61+
]
62+
);
63+
cols[0].colSpan = maxLength;
64+
65+
function arraysEqual(a, b) {
66+
return !(a < b || b < a);
67+
}
68+
69+
var addLevel = function(level, parent, hide) {
70+
var matching = items.filter(function(x) {
71+
return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent);
4772
});
48-
var maxLength = items.reduce(function(a, b) {
49-
return Math.max(a, b.parts.length);
50-
}, 0);
51-
52-
var cols = createRow(table, 'th', ['record', 'seconds']);
53-
cols[0].colSpan = maxLength;
54-
55-
function arraysEqual(a, b) {
56-
return !(a < b || b < a);
73+
if (sort === "number") {
74+
matching = matching.sort(function(a, b) {
75+
return b.value - a.value;
76+
});
77+
} else {
78+
matching = matching.sort();
5779
}
80+
var othersTime = 0;
81+
var othersList = [];
82+
var othersRows = [];
83+
var childrenRows = [];
84+
matching.forEach(function(x) {
85+
var visible = (cutoff === 0 && !hide) || (x.value >= cutoff && !hide);
86+
87+
var cells = [];
88+
for (var i = 0; i < maxLength; i++) {
89+
cells.push(x.parts[i]);
90+
}
91+
cells.push(cutoff === 0 ? x.value : x.value.toFixed(3));
92+
var cols = createRow(table, 'td', cells);
93+
for (i = 0; i < level; i++) {
94+
cols[i].className = 'muted';
95+
}
5896

59-
var addLevel = function(level, parent, hide) {
60-
var matching = items.filter(function(x) {
61-
return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent);
62-
});
63-
var sorted = matching.sort(function(a, b) {
64-
return b.time - a.time;
65-
});
66-
var othersTime = 0;
67-
var othersList = [];
68-
var othersRows = [];
69-
var childrenRows = [];
70-
sorted.forEach(function(x) {
71-
var visible = x.time >= cutoff && !hide;
72-
73-
var cells = [];
74-
for (var i = 0; i < maxLength; i++) {
75-
cells.push(x.parts[i]);
76-
}
77-
cells.push(x.time.toFixed(3));
78-
var cols = createRow(table, 'td', cells);
79-
for (i = 0; i < level; i++) {
80-
cols[i].className = 'muted';
81-
}
82-
83-
var tr = cols[0].parentNode;
84-
if (!visible) {
85-
tr.classList.add("hidden");
86-
}
87-
88-
if (x.time >= cutoff) {
89-
childrenRows.push(tr);
90-
} else {
91-
othersTime += x.time;
92-
othersList.push(x.parts[level]);
93-
othersRows.push(tr);
94-
}
95-
96-
var children = addLevel(level + 1, parent.concat([x.parts[level]]), true);
97-
if (children.length > 0) {
98-
var cell = cols[level];
99-
var onclick = function() {
100-
cell.classList.remove("link");
101-
cell.removeEventListener("click", onclick);
102-
children.forEach(function(x) {
103-
x.classList.remove("hidden");
104-
});
105-
};
106-
cell.classList.add("link");
107-
cell.addEventListener("click", onclick);
108-
}
109-
});
97+
var tr = cols[0].parentNode;
98+
if (!visible) {
99+
tr.classList.add("hidden");
100+
}
110101

111-
if (othersTime > 0) {
112-
var cells = [];
113-
for (var i = 0; i < maxLength; i++) {
114-
cells.push(parent[i]);
115-
}
116-
cells.push(othersTime.toFixed(3));
117-
cells[level] = 'others';
118-
var cols = createRow(table, 'td', cells);
119-
for (i = 0; i < level; i++) {
120-
cols[i].className = 'muted';
121-
}
102+
if (cutoff === 0 || x.value >= cutoff) {
103+
childrenRows.push(tr);
104+
} else {
105+
othersTime += x.value;
106+
othersList.push(x.parts[level]);
107+
othersRows.push(tr);
108+
}
122109

110+
var children = addLevel(level + 1, parent.concat([x.parts[level]]), true);
111+
if (children.length > 0) {
123112
var cell = cols[level];
124-
var tr = cell.parentNode;
125113
var onclick = function() {
126-
tr.classList.add("hidden");
127114
cell.classList.remove("link");
128115
cell.removeEventListener("click", onclick);
129-
othersRows.forEach(function(x) {
116+
children.forEach(function(x) {
130117
x.classList.remove("hidden");
131118
});
132119
};
133-
134-
cell.title = othersList.join(", ");
135120
cell.classList.add("link");
136121
cell.addEventListener("click", onclick);
122+
}
123+
});
137124

138-
if (hide) {
139-
tr.classList.add("hidden");
140-
}
125+
if (othersTime > 0) {
126+
var cells = [];
127+
for (var i = 0; i < maxLength; i++) {
128+
cells.push(parent[i]);
129+
}
130+
cells.push(othersTime.toFixed(3));
131+
cells[level] = 'others';
132+
var cols = createRow(table, 'td', cells);
133+
for (i = 0; i < level; i++) {
134+
cols[i].className = 'muted';
135+
}
141136

142-
childrenRows.push(tr);
137+
var cell = cols[level];
138+
var tr = cell.parentNode;
139+
var onclick = function() {
140+
tr.classList.add("hidden");
141+
cell.classList.remove("link");
142+
cell.removeEventListener("click", onclick);
143+
othersRows.forEach(function(x) {
144+
x.classList.remove("hidden");
145+
});
146+
};
147+
148+
cell.title = othersList.join(", ");
149+
cell.classList.add("link");
150+
cell.addEventListener("click", onclick);
151+
152+
if (hide) {
153+
tr.classList.add("hidden");
143154
}
144155

145-
return childrenRows;
146-
};
156+
childrenRows.push(tr);
157+
}
158+
159+
return childrenRows;
160+
};
147161

148-
addLevel(0, []);
162+
addLevel(0, []);
163+
164+
return table;
165+
}
149166

167+
function showProfile(path, cutoff = 0.05) {
168+
requestGet(path, {}, function(data) {
169+
data.records['total'] = data.total;
170+
const table = createVisualizationTable(data.records, cutoff, "number");
150171
popup(table);
151172
});
152173
}

0 commit comments

Comments
 (0)