add timer info

Signed-off-by: vladmandic <mandic00@live.com>
This commit is contained in:
vladmandic
2026-04-23 12:49:41 +02:00
parent 21b34a6fa7
commit 40e550f1c3
23 changed files with 194 additions and 76 deletions
+4 -2
View File
@@ -48,7 +48,7 @@ function dimensionChange(e, is_width, is_height) {
}
}
onAfterUiUpdate(() => {
function aspectRatioCallback() {
const arPreviewRect = gradioApp().querySelector('#imageARPreview');
if (arPreviewRect) arPreviewRect.style.display = 'none';
const tabImg2img = gradioApp().querySelector('#tab_img2img');
@@ -68,4 +68,6 @@ onAfterUiUpdate(() => {
});
}
}
});
}
onAfterUiUpdate(aspectRatioCallback);
+13 -5
View File
@@ -148,6 +148,7 @@ const engine = {
this.indices.clear();
return;
}
const t0 = performance.now();
const toLoad = enabled.filter((n) => !this.indices.has(n));
const toRemove = [...this.indices.keys()].filter((n) => !enabled.includes(n));
toRemove.forEach((n) => this.indices.delete(n));
@@ -164,7 +165,9 @@ const engine = {
if (cat.name) this.categoryNames[id] = cat.name;
});
}
log('autoComplete', { loaded: name, tags: data.tags?.length || 0 });
const t1 = performance.now();
log('autoComplete', { loaded: name, tags: data.tags?.length || 0, time: Math.round(t1 - t0) });
timer(`autocompleteLoad:${name}`, t1 - t0);
} catch (e) {
log('autoComplete', { failed: name, error: e });
}
@@ -508,6 +511,7 @@ function patchConfigBridge() {
// -- Initialization --
async function initAutocomplete() {
const t0 = performance.now();
const enabled = window.opts?.autocomplete_enabled || [];
active = window.opts?.autocomplete_active || false;
log('autoComplete', { active, enabled });
@@ -543,9 +547,9 @@ async function initAutocomplete() {
attached++;
}
});
log('autoComplete', { attached, dicts: engine.indices.size });
// Reload when settings change
onOptionsChanged(async () => {
async function optionsChangedCallback() {
const newActive = window.opts?.autocomplete_active || false;
const newEnabled = window.opts?.autocomplete_enabled || [];
const currentKeys = [...engine.indices.keys()].sort().join(',');
@@ -556,9 +560,13 @@ async function initAutocomplete() {
active = newActive;
patchActiveButton();
}
});
}
onOptionsChanged(optionsChangedCallback);
// Watch for config updates from the script UI bridge
patchConfigBridge();
patchActiveButton();
onAfterUiUpdate(() => patchConfigBridge());
onAfterUiUpdate(patchConfigBridge);
const t1 = performance.now();
log('autoComplete', { attached, dicts: engine.indices.size, time: Math.round(t1 - t0) });
timer('autocompleteInit', t1 - t0);
}
+4 -1
View File
@@ -17,6 +17,7 @@ function controlInputMode(inputMode, ...args) {
}
async function setupControlUI() {
const t0 = performance.now();
const tabs = ['input', 'output', 'preview'];
for (const tab of tabs) {
const btn = gradioApp().getElementById(`control-${tab}-button`);
@@ -46,5 +47,7 @@ async function setupControlUI() {
});
intersectionObserver.observe(el); // monitor visibility of tab
log('initControlUI');
const t1 = performance.now();
log('setupControlUI', Math.round(t1 - t0));
timer('setupControlUI', t1 - t0);
}
+2
View File
@@ -217,6 +217,7 @@ async function filterExtraNetworksForTab(searchTerm) {
}
const t1 = performance.now();
log(`filterExtraNetworks: text="${searchTerm}" items=${items} match=${found} time=${Math.round(t1 - t0)}`);
timer(`filterExtraNetworks:${searchTerm}`, t1 - t0);
}
function tryToRemoveExtraNetworkFromPrompt(textarea, text) {
@@ -282,6 +283,7 @@ function sortExtraNetworks(fixed = 'no') {
const desc = sortDesc[sortVal];
const t1 = performance.now();
log('sortNetworks', { name: pagename, val: sortVal, order: desc, fixed: fixed === 'fixed', items: num, time: Math.round(t1 - t0) });
timer(`sortExtraNetworks:${desc}`, t1 - t0);
return desc;
}
+11 -4
View File
@@ -855,7 +855,8 @@ async function gallerySearch() {
}
const t1 = performance.now();
updateStatusWithSort('Filter', ['Images', `${totalFound.toLocaleString()} / ${allFiles.length.toLocaleString()}`], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
updateStatusWithSort('Filter', ['Images', `${totalFound.toLocaleString()} / ${allFiles.length.toLocaleString()}`], `${iconStopwatch} ${Math.round(t1 - t0).toLocaleString()}ms`);
timer(`galleryFilter:${str}`, t1 - t0);
refreshGallerySelection();
}, 250);
}
@@ -936,7 +937,8 @@ async function gallerySort(key) {
const t1 = performance.now();
log(`gallerySort: sort=${sortMode.name} len=${arr.length} time=${Math.floor(t1 - t0)}`);
updateStatusWithSort(['Images', arr.length.toLocaleString()], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
updateStatusWithSort(['Images', arr.length.toLocaleString()], `${iconStopwatch} ${Math.round(t1 - t0).toLocaleString()}ms`);
timer(`gallerySort:${sortMode.name}`, t1 - t0);
refreshGallerySelection();
}
@@ -1025,7 +1027,8 @@ async function thumbCacheCleanup(folder, imgCount, controller, force = false) {
await idbFolderCleanup(keptGalleryHashes, recursiveFolder, controller.signal)
.then((delcount) => {
const t1 = performance.now();
log(`Thumbnail DB cleanup: folder=${folder} kept=${keptGalleryHashes.size} deleted=${delcount} time=${Math.floor(t1 - t0)}ms`);
log(`Thumbnail DB cleanup: folder=${folder} kept=${keptGalleryHashes.size} deleted=${delcount} time=${Math.round(t1 - t0)}ms`);
timer(`thumbnailDBCleanup:${folder}`, t1 - t0);
currentGalleryFolder = null;
el.clearCacheFolder.innerText = '<select a folder first>';
updateStatusWithSort('Thumbnail cache cleared');
@@ -1139,6 +1142,7 @@ async function fetchFilesHT(evt, controller) {
const t1 = performance.now();
log(`gallery: folder=${evt.target.name} num=${numFiles} time=${Math.floor(t1 - t0)}ms`);
timer(`galleryFetch:${evt.target.name}`, t1 - t0);
updateStatusWithSort(['Folder', evt.target.name], ['Images', numFiles.toLocaleString()], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
galleryProgressBar.start(numFiles);
addSeparators();
@@ -1320,7 +1324,7 @@ async function blockQueueUntilReady() {
}
async function initGallery() { // triggered on gradio change to monitor when ui gets sufficiently constructed
log('initGallery');
const t0 = performance.now();
el.folders = gradioApp().getElementById('tab-gallery-folders');
el.files = gradioApp().getElementById('tab-gallery-files');
el.status = gradioApp().getElementById('tab-gallery-status');
@@ -1363,6 +1367,9 @@ async function initGallery() { // triggered on gradio change to monitor when ui
'outdir_img2img_grids',
'outdir_control_grids',
].forEach((op) => { monitorOption(op, updateFolders); });
const t1 = performance.now();
log('initGallery', Math.round(t1 - t0));
timer('initGallery', t1 - t0);
}
// register on startup
+4 -1
View File
@@ -20,6 +20,7 @@ let control_gallery;
let modal;
async function initiGenerationParams() {
const t0 = performance.now();
if (!modal) modal = gradioApp().getElementById('lightboxModal');
if (!modal) return;
@@ -37,5 +38,7 @@ async function initiGenerationParams() {
if (!img2img_gallery) img2img_gallery = attachGalleryListeners('img2img');
if (!control_gallery) control_gallery = attachGalleryListeners('control');
modalObserver.observe(modal, { attributes: true, attributeFilter: ['style'] });
log('initGenerationParams');
const t1 = performance.now();
log('initGenerationParams', Math.round(t1 - t0));
timer('initGenerationParams', t1 - t0);
}
+4 -1
View File
@@ -235,6 +235,7 @@ async function bindImageViewer() {
}
async function initImageViewer() {
const t0 = performance.now();
// main elements
const modal = document.createElement('div');
modal.id = 'lightboxModal';
@@ -341,7 +342,9 @@ async function initImageViewer() {
modal.append(modalExif);
gradioApp().appendChild(modal);
log('initImageViewer');
const t1 = performance.now();
log('initImageViewer', Math.round(t1 - t0));
timer('initImageViewer', t1 - t0);
}
onAfterUiUpdate(bindImageViewer);
+1
View File
@@ -66,6 +66,7 @@ async function removeSplash() {
log('removeSplash');
const t = Math.round(performance.now() - appStartTime);
log('startupTime', t);
timer('splashVisible', t);
xhrPost(`${window.api}/log`, { message: `ready time=${t}` });
monitorLogActive = false;
}
+4 -1
View File
@@ -103,6 +103,7 @@ async function logMonitor() {
async function initLogMonitor() {
const el = document.getElementsByTagName('footer')[0];
if (!el) return;
const t0 = performance.now();
el.classList.add('log-monitor');
const ui_disabled = Array.isArray(window.opts.ui_disabled) ? window.opts.ui_disabled : [];
if (ui_disabled.includes('logs')) return;
@@ -126,5 +127,7 @@ async function initLogMonitor() {
el.style.display = 'none';
authFetch(`${window.api}/start?agent=${encodeURI(navigator.userAgent)}`);
logMonitor();
log('initLogMonitor');
const t1 = performance.now();
log('initLogMonitor', Math.round(t1 - t0));
timer('initLogMonitor', t1 - t0);
}
+4 -1
View File
@@ -27,7 +27,7 @@ function setupBracketChecking(idPrompt, idCounter) {
}
async function initPromptChecker() {
log('initPromptChecker');
const t0 = performance.now();
setupBracketChecking('txt2img_prompt', 'txt2img_token_counter');
setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter');
setupBracketChecking('img2img_prompt', 'img2img_token_counter');
@@ -36,4 +36,7 @@ async function initPromptChecker() {
setupBracketChecking('control_neg_prompt', 'control_negative_token_counter');
setupBracketChecking('video_prompt', 'video_token_counter');
setupBracketChecking('video_neg_prompt', 'video_negative_token_counter');
const t1 = performance.now();
log('initPromptChecker', Math.round(t1 - t0));
timer('initPromptChecker', t1 - t0);
}
+6 -2
View File
@@ -1,3 +1,5 @@
window.gradioObserver = null;
async function sleep(ms) {
return new Promise((resolve) => { setTimeout(resolve, ms); });
}
@@ -15,6 +17,7 @@ function logFn(func) { // not recommended: use log, debug or error explicitly
const returnValue = func(...arguments);
const t1 = performance.now();
log(func.name, `time=${Math.round(t1 - t0)}`);
timer(func.name, t1 - t0);
return returnValue;
};
}
@@ -95,6 +98,7 @@ function executeCallbacks(queue, arg) {
callback(arg);
const t1 = performance.now();
if (t1 - t0 > 250) log('callbackSlow', callback.name || callback, `time=${Math.round(t1 - t0)}`);
timer(callback.name || 'anonymousCallback', t1 - t0);
} catch (e) {
error(`executeCallbacks: ${callback} ${e}`);
}
@@ -149,8 +153,8 @@ async function mutationCallback(mutations) {
document.addEventListener('DOMContentLoaded', () => {
log('DOMContentLoaded');
const mutationObserver = new MutationObserver(mutationCallback);
mutationObserver.observe(gradioApp(), { childList: true, subtree: true, attributes: false });
window.gradioObserver = new MutationObserver(mutationCallback);
window.gradioObserver.observe(gradioApp(), { childList: true, subtree: true, attributes: false });
});
/**
+7 -6
View File
@@ -1,3 +1,4 @@
window.hintsObserver = null;
const allLocales = ['en', 'tb', 'nb', 'hr', 'es', 'it', 'fr', 'de', 'pt', 'ru', 'zh', 'ja', 'ko', 'hi', 'ar', 'bn', 'ur', 'id', 'vi', 'tr', 'sr', 'po', 'he', 'xx', 'qq', 'tlh'];
const localeData = {
prev: null,
@@ -11,7 +12,6 @@ const localeData = {
btn: null,
expandTimeout: null, // Property for expansion timeout
currentElement: null, // Track current element for expansion
observer: null, // MutationObserver for DOM changes
};
let localeTimeout = null;
const isTouchDevice = 'ontouchstart' in window;
@@ -73,7 +73,7 @@ async function tooltipCreate() {
gradioApp().addEventListener('pointerover', tooltipShowDelegated); // eslint-disable-line no-use-before-define
gradioApp().addEventListener('pointerout', tooltipHideDelegated); // eslint-disable-line no-use-before-define
}
if (!localeData.observer) initializeDOMObserver(); // eslint-disable-line no-use-before-define
if (!window.hintsObserver) initializeDOMObserver(); // eslint-disable-line no-use-before-define
}
async function expandTooltip(element, longHint) {
@@ -345,6 +345,7 @@ async function setHints() {
localeData.finished = true;
localeData.initial = false;
const t1 = performance.now();
timer('setHints', t1 - t0);
// localeData.btn.style.backgroundColor = localeData.locale !== 'en' ? 'var(--primary-500)' : '';
log('touchDevice', isTouchDevice);
log('setHints', { type: localeData.type, locale: localeData.locale, elements: elements.length, localized, hints, data: localeData.data.length, override: overrideData.length, time: Math.round(t1 - t0) });
@@ -379,11 +380,11 @@ async function applyHintToElement(el) {
// Initialize MutationObserver for immediate hint application
function initializeDOMObserver() {
if (localeData.observer) {
localeData.observer.disconnect();
if (window.hintsObserver) {
window.hintsObserver.disconnect();
}
localeData.observer = new MutationObserver((mutations) => {
window.hintsObserver = new MutationObserver((mutations) => {
// Process added nodes immediately
for (const mutation of mutations) {
if (mutation.type === 'childList') {
@@ -421,7 +422,7 @@ function initializeDOMObserver() {
// Start observing the entire gradio app for changes
const targetNode = gradioApp();
if (targetNode) {
localeData.observer.observe(targetNode, {
window.hintsObserver.observe(targetNode, {
childList: true,
subtree: true,
});
+7 -3
View File
@@ -46,9 +46,7 @@ async function updateOpts(json_string) {
}
}
const t2 = performance.now();
window.opts = new_opts;
log('updateOpts', `settings=${Object.keys(new_opts).length} callbacks=${Math.round(t2 - t1)} apply=${Math.round(t1 - t0)}`);
Object.entries(opts_metadata).forEach(([opt, meta]) => {
if (!opts_tabs[meta.tab_name]) opts_tabs[meta.tab_name] = {};
if (!opts_tabs[meta.tab_name].unsaved_keys) opts_tabs[meta.tab_name].unsaved_keys = new Set();
@@ -56,6 +54,9 @@ async function updateOpts(json_string) {
if (!meta.is_stored) opts_tabs[meta.tab_name].unsaved_keys.add(opt);
else opts_tabs[meta.tab_name].saved_keys.add(opt);
});
const t2 = performance.now();
log('updateOpts', `settings=${Object.keys(new_opts).length} callbacks=${Math.round(t2 - t1)} apply=${Math.round(t1 - t0)}`);
timer('updateOpts', t2 - t0);
}
function showAllSettings() {
@@ -201,6 +202,7 @@ async function initModels() {
async function initSettings() {
if (settingsInitialized) return;
const t0 = performance.now();
settingsInitialized = true;
const tabNavElements = gradioApp().querySelector('#settings > .tab-nav');
if (!tabNavElements) {
@@ -228,5 +230,7 @@ async function initSettings() {
tabContentWrapper.appendChild(elem);
observer.observe(elem, { attributes: true, attributeFilter: ['style'] });
});
log('initSettings');
const t1 = performance.now();
log('initSettings', Math.round(t1 - t0));
timer('initSettings', t1 - t0);
}
+42 -23
View File
@@ -2,6 +2,8 @@
window.api = '/sdapi/v1';
window.subpath = '';
const startupPromises = [];
async function waitForOpts() {
// make sure all of the ui is ready and options are loaded
const t0 = performance.now();
@@ -14,7 +16,8 @@ async function waitForOpts() {
if (window.opts && Object.keys(window.opts).length > 0) {
ok = window.opts.theme_type === 'Modern' ? 'uiux_separator_appearance' in window.opts : true;
if (ok) {
log('waitForOpts', `time=${Math.round(t1 - t0)}`);
log('waitForOpts', Math.round(t1 - t0));
timer('waitForOpts', t1 - t0);
break;
}
}
@@ -23,54 +26,70 @@ async function waitForOpts() {
}
}
async function postStartup() {
log('postStartup');
if (window.gradioObserver) window.gradioObserver.disconnect();
if (window.hintsObserver) window.hintsObserver.disconnect();
logTimers();
}
async function initStartup() {
const t0 = performance.now();
log('initGradio', `time=${Math.round(t0 - appStartTime)}`);
log('initGradio', Math.round(t0 - appStartTime));
timer('initGradio', t0 - appStartTime);
log('initUi');
if (window.setupLogger) await setupLogger();
// all items here are non-blocking async calls
initModels();
getUIDefaults();
initPromptChecker();
initContextMenu();
initDragDrop();
initAccordions();
initSettings();
initImageViewer();
initiGenerationParams();
initChangelog();
setupControlUI();
startupPromises.push(initModels());
startupPromises.push(getUIDefaults());
startupPromises.push(initPromptChecker());
startupPromises.push(initContextMenu());
startupPromises.push(initDragDrop());
startupPromises.push(initAccordions());
startupPromises.push(initSettings());
startupPromises.push(initImageViewer());
startupPromises.push(initiGenerationParams());
startupPromises.push(initChangelog());
startupPromises.push(setupControlUI());
// reconnect server session
await reconnectUI();
await waitForOpts();
await initGallery();
log('mountURL', window.opts.subpath);
if (window.opts.subpath?.length > 0) {
window.subpath = window.opts.subpath;
window.api = `${window.subpath}/sdapi/v1`;
}
setRefreshInterval();
executeCallbacks(uiReadyCallbacks);
setupExtraNetworks();
startupPromises.push(initGallery());
startupPromises.push(setRefreshInterval());
startupPromises.push(setupExtraNetworks());
// optinally wait for modern ui
if (window.waitForUiReady) await waitForUiReady();
initAutocomplete();
monitorConnection();
// post startup tasks that may take longer but are not critical
showNetworks();
setHints();
applyStyles();
initIndexDB();
initLogMonitor();
startupPromises.push(initAutocomplete());
startupPromises.push(monitorConnection());
startupPromises.push(showNetworks());
startupPromises.push(setHints());
startupPromises.push(applyStyles());
startupPromises.push(initIndexDB());
startupPromises.push(initLogMonitor());
t1 = performance.now();
log('initStartup', Math.round(1000 * (t1 - t0) / 1000000));
removeSplash();
await Promise.all(startupPromises);
t2 = performance.now();
log('initComplete', Math.round(1000 * (t2 - t0) / 1000000));
postStartup();
}
onUiLoaded(initStartup);
+14
View File
@@ -0,0 +1,14 @@
const allTimers = [];
async function timer(name, elapsed) {
allTimers.push([name, Math.round(elapsed)]);
}
async function logTimers() {
allTimers.sort((a, b) => b[1] - a[1]);
const filteredTimers = allTimers.filter((t) => t[1] > 50);
log('timers', filteredTimers);
// xhrPost(`${window.api}/log`, { debug: JSON.stringify(filteredTimers) });
}
window.timer = timer;
+9 -2
View File
@@ -163,6 +163,7 @@ function setFontSize(val, old) {
appliedFontSize = nextSize;
const t1 = performance.now();
log('setFontSize', nextSize, `time=${Math.round(t1 - t0)}`);
timer('setFontSize', t1 - t0);
});
}
@@ -473,6 +474,7 @@ function registerTextareaCallback() {
// sortUIElements();
if (promptsInitialized) return;
if (promptRegistrationInProgress) return;
const t0 = performance.now();
const app = gradioApp();
if (!app) return;
@@ -540,7 +542,9 @@ function registerTextareaCallback() {
promptsInitialized = registeredPromptIds.size === total;
if (promptsInitialized) {
promptRegistrationInProgress = false;
log('initPrompts', registeredPromptIds.size);
const t1 = performance.now();
log('initPrompts', { count: registeredPromptIds.size, time: Math.round(t1 - t0) });
timer('initPrompts', t1 - t0);
return;
}
@@ -709,6 +713,7 @@ async function browseFolder() {
}
async function reconnectUI() {
const t0 = performance.now();
const gallery = gradioApp().getElementById('txt2img_gallery');
const task_id = localStorage.getItem('task');
const api_logo = Array.from(gradioApp().querySelectorAll('img')).filter((el) => el?.src?.endsWith('api-logo.svg'));
@@ -738,5 +743,7 @@ async function reconnectUI() {
};
const sd_model_observer = new MutationObserver(sd_model_callback);
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true });
log('reconnectUI');
const t1 = performance.now();
log('reconnectUI', Math.round(t1 - t0));
timer('reconnectUI', t1 - t0);
}