5a3be3af33b76d69d1fc98ee76b9a37f96e96fc7 max Wed Aug 26 00:36:52 2026 -0700 Add opt-in per-phase request timing to the new hgBlat and hgSession pages, shown in a dialog with &measureTiming=1. refs #38157 New reusable perfTimer collector (lib/perfTimer.c) records labeled wall-clock intervals via clock1000() and emits them as JSON; hgBlat and hgSession attach a timing array to their payload when the existing measureTiming cart/CGI var is set. A shared gbShowTimingDialog helper in utils.js renders the server phases plus a client render-time row in a house-style modal, which opens automatically when measureTiming is on. Confirms the position band/locus annotation loop dominates hgSession, and run-BLAT plus locus lookups dominate hgBlat. diff --git src/hg/js/utils.js src/hg/js/utils.js index 527b53e3ead..c7cf1aa7825 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -4321,30 +4321,108 @@ /* Actually hides the tooltip text */ ele.classList.remove("isShown"); ele.style.opacity = "0"; ele.style.visibility = "hidden"; } function titleTagToMouseover(mapEl) { /* for a given area tag, extract the title text into a div that can be positioned * like a standard tooltip mouseover next to the item */ if (mapEl.dataset.tooltip) addMouseover(mapEl, mapEl.dataset.tooltip); else addMouseover(mapEl, mapEl.title); } +function gbShowTimingDialog(serverRows, clientRows) { + /* Pop up a small modal that breaks down where a page spent its time. Shared by the + * client-rendered CGI pages (hgBlat, hgSession, ...) that emit a "timing" array when loaded + * with &measureTiming=1. serverRows and clientRows are each an array of {label, ms} (either may + * be null/empty); the server list normally ends with a {label:"total"} row from the C side. + * Renders one gbTable with a proportional bar per row, styled by the .gbTiming* rules in + * gbModern.css. Reuses the .gbModalBg/.gbModal machinery; closes on Close, Esc, backdrop. */ + serverRows = serverRows || []; + clientRows = clientRows || []; + // Scale the bars to the largest single interval (ignoring the grand-total rows, which would + // otherwise dwarf every step). Fall back to 1 to avoid divide-by-zero on an all-zero page. + var maxMs = 1; + function scan(rows) { + rows.forEach(function(r) { + if (r.label !== "total" && r.ms > maxMs) + maxMs = r.ms; + }); + } + scan(serverRows); + scan(clientRows); + + function rowHtml(r, extraClass) { + var pct = Math.min(100, Math.round((r.ms / maxMs) * 100)); + var isTotal = (r.label === "total"); + var label = isTotal ? "Total" : r.label; + return '
| Phase | ' + + 'ms | ' + + '' + + ' |
|---|
&measureTiming=1 from the page URL to toggle ' +
+ 'this report.