function createRow(table, cellName, items) { var tr = document.createElement('tr'); var res = []; items.forEach(function(x, i) { if (x === undefined) { res.push(null); return; } var td = document.createElement(cellName); td.textContent = x; tr.appendChild(td); res.push(td); var colspan = 1; for (var n = i + 1; n < items.length; n++) { if (items[n] !== undefined) { break; } colspan += 1; } if (colspan > 1) { td.colSpan = colspan; } }); table.appendChild(tr); return res; } function showProfile(path, cutoff = 0.05) { requestGet(path, {}, function(data) { var table = document.createElement('table'); table.className = 'popup-table'; data.records['total'] = data.total; var keys = Object.keys(data.records).sort(function(a, b) { return data.records[b] - data.records[a]; }); var items = keys.map(function(x) { return {key: x, parts: x.split('/'), time: data.records[x]}; }); var maxLength = items.reduce(function(a, b) { return Math.max(a, b.parts.length); }, 0); var cols = createRow(table, 'th', ['record', 'seconds']); cols[0].colSpan = maxLength; function arraysEqual(a, b) { return !(a < b || b < a); } var addLevel = function(level, parent, hide) { var matching = items.filter(function(x) { return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent); }); var sorted = matching.sort(function(a, b) { return b.time - a.time; }); var othersTime = 0; var othersList = []; var othersRows = []; var childrenRows = []; sorted.forEach(function(x) { var visible = x.time >= cutoff && !hide; var cells = []; for (var i = 0; i < maxLength; i++) { cells.push(x.parts[i]); } cells.push(x.time.toFixed(3)); var cols = createRow(table, 'td', cells); for (i = 0; i < level; i++) { cols[i].className = 'muted'; } var tr = cols[0].parentNode; if (!visible) { tr.classList.add("hidden"); } if (x.time >= cutoff) { childrenRows.push(tr); } else { othersTime += x.time; othersList.push(x.parts[level]); othersRows.push(tr); } var children = addLevel(level + 1, parent.concat([x.parts[level]]), true); if (children.length > 0) { var cell = cols[level]; var onclick = function() { cell.classList.remove("link"); cell.removeEventListener("click", onclick); children.forEach(function(x) { x.classList.remove("hidden"); }); }; cell.classList.add("link"); cell.addEventListener("click", onclick); } }); if (othersTime > 0) { var cells = []; for (var i = 0; i < maxLength; i++) { cells.push(parent[i]); } cells.push(othersTime.toFixed(3)); cells[level] = 'others'; var cols = createRow(table, 'td', cells); for (i = 0; i < level; i++) { cols[i].className = 'muted'; } var cell = cols[level]; var tr = cell.parentNode; var onclick = function() { tr.classList.add("hidden"); cell.classList.remove("link"); cell.removeEventListener("click", onclick); othersRows.forEach(function(x) { x.classList.remove("hidden"); }); }; cell.title = othersList.join(", "); cell.classList.add("link"); cell.addEventListener("click", onclick); if (hide) { tr.classList.add("hidden"); } childrenRows.push(tr); } return childrenRows; }; addLevel(0, []); popup(table); }); }