Display emulation execution time

This commit is contained in:
momo5502
2025-10-09 20:30:45 +02:00
parent 286c73ff2e
commit 04e02094ab
3 changed files with 106 additions and 23 deletions

View File

@@ -1,9 +1,16 @@
import { EmulationStatus } from "@/emulator";
import { TextTooltip } from "./text-tooltip";
import { BarChartSteps, CpuFill, FloppyFill } from "react-bootstrap-icons";
import {
BarChartSteps,
CpuFill,
FloppyFill,
StopwatchFill,
} from "react-bootstrap-icons";
import React from "react";
export interface EmulationSummaryProps {
status?: EmulationStatus;
executionTimeFetcher: () => number;
}
function formatMemory(value: BigInt): string {
@@ -20,27 +27,75 @@ function formatMemory(value: BigInt): string {
return num.toFixed(2) + " " + abbr[index];
}
export function EmulationSummary(props: EmulationSummaryProps) {
if (!props.status) {
return <></>;
function formatTime(seconds: number): string {
const hrs = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
const secsString = secs < 10 ? "0" + secs : secs.toString();
if (hrs > 0) {
const minsString = mins < 10 ? "0" + mins : mins.toString();
return `${hrs.toString()}:${minsString}:${secsString}`;
}
return (
<div className="emulation-summary terminal-glass items-center absolute z-49 right-0 m-6 rounded-xl min-w-[150px] p-3 text-white cursor-default font-medium text-right text-sm whitespace-nowrap leading-6 font-mono">
<TextTooltip tooltip={"Active threads"}>
{props.status.activeThreads}
<BarChartSteps className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Application memory"}>
{formatMemory(props.status.committedMemory)}
<FloppyFill className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Executed instructions"}>
{props.status.executedInstructions.toLocaleString()}
<CpuFill className="inline ml-3" />
</TextTooltip>
</div>
);
return `${mins.toString()}:${secsString}`;
}
export class EmulationSummary extends React.Component<
EmulationSummaryProps,
{}
> {
private timer: NodeJS.Timeout | undefined = undefined;
constructor(props: EmulationSummaryProps) {
super(props);
}
componentDidMount(): void {
if (this.timer) {
clearInterval(this.timer);
}
this.timer = setInterval(() => {
this.forceUpdate();
}, 200);
}
componentWillUnmount(): void {
if (this.timer) {
clearInterval(this.timer);
this.timer = undefined;
}
}
render() {
if (!this.props.status) {
return <></>;
}
return (
<div className="emulation-summary terminal-glass items-center absolute z-49 right-0 m-6 rounded-xl min-w-[150px] p-3 text-white cursor-default font-medium text-right text-sm whitespace-nowrap leading-6 font-mono">
<TextTooltip tooltip={"Active Threads"}>
{this.props.status.activeThreads}
<BarChartSteps className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Application Memory"}>
{formatMemory(this.props.status.committedMemory)}
<FloppyFill className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Executed Instructions"}>
{this.props.status.executedInstructions.toLocaleString()}
<CpuFill className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Execution Time"}>
{formatTime(this.props.executionTimeFetcher() / 1000)}
<StopwatchFill className="inline ml-3" />
</TextTooltip>
</div>
);
}
}

View File

@@ -85,6 +85,9 @@ export class Emulator {
worker: Worker;
state: EmulationState = EmulationState.Stopped;
exit_status: number | null = null;
start_time: Date = new Date();
pause_time: Date | null = null;
paused_time: number = 0;
constructor(
logHandler: LogHandler,
@@ -109,6 +112,9 @@ export class Emulator {
}
async start(settings: Settings, file: string) {
this.start_time = new Date();
this.pause_time = null;
this.paused_time = 0;
this._setState(EmulationState.Running);
this.stautsUpdateHandler(createDefaultEmulationStatus());
@@ -184,6 +190,12 @@ export class Emulator {
this.updateState();
}
getExecutionTime() {
const endTime = this.pause_time ? this.pause_time : new Date();
const totalTime = endTime.getTime() - this.start_time.getTime();
return totalTime - this.paused_time;
}
logError(message: string) {
this.logHandler([`<span class="terminal-red">${message}</span>`]);
}
@@ -233,6 +245,14 @@ export class Emulator {
_setState(state: EmulationState) {
this.state = state;
if (isFinalState(this.state) || this.state === EmulationState.Paused) {
this.pause_time = new Date();
} else if (this.state == EmulationState.Running && this.pause_time) {
this.paused_time += new Date().getTime() - this.pause_time.getTime();
this.pause_time = null;
}
this.stateChangeHandler(this.state);
}

View File

@@ -130,6 +130,7 @@ export class Playground extends React.Component<
this.start = this.start.bind(this);
this.resetFilesys = this.resetFilesys.bind(this);
this.startEmulator = this.startEmulator.bind(this);
this.fetchExecutionTime = this.fetchExecutionTime.bind(this);
this.toggleEmulatorState = this.toggleEmulatorState.bind(this);
this.state = {
@@ -162,6 +163,10 @@ export class Playground extends React.Component<
});
}
fetchExecutionTime() {
return this.state.emulator ? this.state.emulator.getExecutionTime() : 0;
}
async resetFilesys() {
if (!this.state.filesystem) {
return;
@@ -440,7 +445,10 @@ export class Playground extends React.Component<
</div>
</header>
<div className="flex flex-1">
<EmulationSummary status={this.state.emulationStatus} />
<EmulationSummary
status={this.state.emulationStatus}
executionTimeFetcher={this.fetchExecutionTime}
/>
<div className="flex flex-1 flex-col pl-1 overflow-auto">
<Output ref={this.output} />
</div>