Skip to content

Commit 57c2177

Browse files
committed
feat: time user interactions
Instead of saying "done in xxx ms" for the whole debugging session, instead show the performance of the last button click.
1 parent a2fe33e commit 57c2177

File tree

1 file changed

+112
-83
lines changed

1 file changed

+112
-83
lines changed

pages/index.astro

+112-83
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const vis = {
100100
},
101101
printErr: function (text: any) {
102102
stdioEl.value += text + '\n';
103+
console.error(text);
103104
},
104105
} as any; /* TODO: emscripten types */
105106

@@ -542,6 +543,15 @@ const vis = {
542543
self['__destroy__']();
543544
}
544545

546+
function withTiming(f: Function, start?: PerformanceMeasure) {
547+
start = start ?? window.performance.mark('talvos');
548+
549+
return (async () => f())().finally(() => {
550+
const call = window.performance.measure(start.name, start.name);
551+
rootEl.querySelector<HTMLOutputElement>('output.timing')!.value = `done in ${call.duration}ms`;
552+
});
553+
}
554+
545555
// TODO refactor into `withTiming` / `withExec` ?
546556
function captureOutput(f: Function, start?: PerformanceMeasure) {
547557
stdioEl.value = '';
@@ -642,105 +652,124 @@ const vis = {
642652
const text = (rootEl.querySelector('.module') as { value: string } | null)!.value;
643653

644654
const start = window.performance.mark('debug', { detail: { text } });
645-
const session = new (await Session)(text);
646-
// session.params.EntryName = 'vecadd';
647-
session.params.EntryName = entryEl.selectedOptions.item(0)?.value ?? 'main';
648-
649-
const debugCtrl = rootEl.querySelector<HTMLElement>('.debugger')!;
655+
withTiming(async () => {
656+
const session = new (await Session)(text);
657+
// session.params.EntryName = 'vecadd';
658+
session.params.EntryName = entryEl.selectedOptions.item(0)?.value ?? 'main';
650659

651-
function finish() {
652-
debugCtrl.hidden = true;
653-
// remove references to 1) allow the session to be GC'd, and 2) safety of the dangling pointer
654-
debugCtrl.querySelectorAll<HTMLButtonElement>('button').forEach((el) => (el.onclick = null));
655-
rootEl
656-
.querySelectorAll<HTMLButtonElement>('button.exec,textarea')
657-
.forEach((el) => el.removeAttribute('disabled'));
658-
window.dispatchEvent(ev_finish);
660+
const debugCtrl = rootEl.querySelector<HTMLElement>('.debugger')!;
659661

660-
destroy(session);
662+
function finish() {
663+
withTiming(() => {
664+
debugCtrl.hidden = true;
665+
// remove references to 1) allow the session to be GC'd, and 2) safety of the dangling pointer
666+
debugCtrl.querySelectorAll<HTMLButtonElement>('button').forEach((el) => (el.onclick = null));
667+
rootEl
668+
.querySelectorAll<HTMLButtonElement>('button.exec,textarea')
669+
.forEach((el) => el.removeAttribute('disabled'));
670+
window.dispatchEvent(ev_finish);
661671

662-
const call = window.performance.measure(start.name, start.name);
663-
rootEl.querySelector<HTMLOutputElement>('output.timing')!.value = `done in ${call.duration}ms`;
664-
}
665-
666-
try {
667-
session.start();
668-
window.dispatchEvent(ev_start);
669-
670-
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
671-
session.printContext();
672-
} catch (e) {
673-
finish();
674-
throw e;
675-
}
672+
destroy(session);
673+
}, window.performance.mark('finish'));
676674

677-
const FINISHED = 1; // TODO sync with talvos::PipelineExecutor::StepResult
675+
const call = window.performance.measure(start.name, start.name);
676+
// we need to be scheduled after the (async) bits in `withTiming`
677+
// this is good and will in no way be broken by anything I do later
678+
setTimeout(
679+
() =>
680+
(rootEl.querySelector<HTMLOutputElement>('output.timing')!.value +=
681+
` (session lifetime: ${call.duration}ms)`),
682+
0
683+
);
684+
}
678685

679-
debugCtrl.querySelector<HTMLButtonElement>('button.tick')!.onclick = async function () {
680-
stdioEl.value = '';
681-
errorEl.value = '';
682686
try {
683-
const last = await session.tick();
684-
window.dispatchEvent(ev_tick);
685-
if (last == FINISHED) {
686-
finish();
687-
}
687+
session.start();
688+
window.dispatchEvent(ev_start);
688689

689-
// TODO remove (confusing)
690690
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
691691
session.printContext();
692692
} catch (e) {
693693
finish();
694694
throw e;
695695
}
696-
};
697-
debugCtrl.querySelector<HTMLButtonElement>('button.step')!.onclick = async function () {
698-
stdioEl.value = '';
699-
errorEl.value = '';
700-
try {
701-
const last = await session.step();
702-
window.dispatchEvent(ev_step);
703-
if (last == FINISHED) {
704-
finish();
705-
}
706696

707-
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
708-
session.printContext();
709-
} catch (e) {
710-
finish();
711-
throw e;
712-
}
713-
};
714-
debugCtrl.querySelector<HTMLButtonElement>('button.switch')!.onclick = function () {
715-
const input = prompt('Usage: switch: X [Y [Z]]', 'X [Y [Z]]'); // %15 is `void` in vecadd
716-
if (input == null) {
717-
return;
718-
}
719-
const args = input.split(/\s+/);
720-
session.switch(args);
721-
};
722-
debugCtrl.querySelector<HTMLButtonElement>('button.print')!.onclick = function () {
723-
const input = prompt('Usage: print: %<id>', '%15'); // %15 is `void` in vecadd
724-
if (input == null) {
725-
return;
726-
}
727-
const args = input.split(/\s+/);
728-
session.print(args);
729-
};
697+
const FINISHED = 1; // TODO sync with talvos::PipelineExecutor::StepResult
730698

731-
debugCtrl.querySelector<HTMLButtonElement>('button.stop')!.onclick = finish;
732-
debugCtrl.querySelector<HTMLButtonElement>('button.continue')!.onclick = function () {
733-
stdioEl.value = '';
734-
errorEl.value = '';
735-
try {
736-
session.continue();
737-
} finally {
738-
// TODO breakpoints
739-
finish();
740-
}
741-
};
699+
debugCtrl.querySelector<HTMLButtonElement>('button.tick')!.onclick = async function () {
700+
stdioEl.value = '';
701+
errorEl.value = '';
702+
const start = window.performance.mark('tick', { detail: {} });
703+
withTiming(async () => {
704+
try {
705+
const last = await session.tick();
706+
window.dispatchEvent(ev_tick);
707+
if (last == FINISHED) {
708+
finish();
709+
}
742710

743-
debugCtrl.hidden = false;
711+
// TODO remove (confusing)
712+
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
713+
session.printContext();
714+
} catch (e) {
715+
finish();
716+
throw e;
717+
}
718+
}, start);
719+
};
720+
debugCtrl.querySelector<HTMLButtonElement>('button.step')!.onclick = async function () {
721+
stdioEl.value = '';
722+
errorEl.value = '';
723+
const start = window.performance.mark('step', { detail: {} });
724+
withTiming(async () => {
725+
try {
726+
const last = await session.step();
727+
window.dispatchEvent(ev_step);
728+
if (last == FINISHED) {
729+
finish();
730+
}
731+
732+
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
733+
session.printContext();
734+
} catch (e) {
735+
finish();
736+
throw e;
737+
}
738+
}, start);
739+
};
740+
debugCtrl.querySelector<HTMLButtonElement>('button.switch')!.onclick = function () {
741+
const input = prompt('Usage: switch: X [Y [Z]]', 'X [Y [Z]]'); // %15 is `void` in vecadd
742+
if (input == null) {
743+
return;
744+
}
745+
const args = input.split(/\s+/);
746+
session.switch(args);
747+
};
748+
debugCtrl.querySelector<HTMLButtonElement>('button.print')!.onclick = function () {
749+
const input = prompt('Usage: print: %<id>', '%15'); // %15 is `void` in vecadd
750+
if (input == null) {
751+
return;
752+
}
753+
const args = input.split(/\s+/);
754+
session.print(args);
755+
};
756+
757+
debugCtrl.querySelector<HTMLButtonElement>('button.stop')!.onclick = finish;
758+
debugCtrl.querySelector<HTMLButtonElement>('button.continue')!.onclick = function () {
759+
stdioEl.value = '';
760+
errorEl.value = '';
761+
withTiming(() => {
762+
try {
763+
session.continue();
764+
} finally {
765+
// TODO breakpoints
766+
finish();
767+
}
768+
});
769+
};
770+
771+
debugCtrl.hidden = false;
772+
}, start);
744773
};
745774

746775
const entryEl = rootEl.querySelector<HTMLSelectElement>('select[name="entry"]')!;

0 commit comments

Comments
 (0)