feat: add benchmark settings panel
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m59s

This commit is contained in:
2024-05-01 23:05:04 +02:00
parent 8bf2958e1d
commit d9afec5bf6
39 changed files with 1253 additions and 741 deletions

View File

@@ -0,0 +1,48 @@
<script lang="ts">
export let labels: string[] = [];
export let values: number[] = [];
$: total = values.reduce((acc, v) => acc + v, 0);
let colors = ["red", "green", "blue"];
</script>
<div class="wrapper">
<div class="bars">
{#each values as value, i}
<div class="bar bg-{colors[i]}" style="width: {(value / total) * 100}%;">
{Math.round(value)}ms
</div>
{/each}
</div>
<div class="labels mt-2">
{#each values as _label, i}
<div class="text-{colors[i]}">{labels[i]}</div>
{/each}
</div>
<span
class="bg-red bg-green bg-yellow bg-blue text-red text-green text-yellow text-blue"
></span>
</div>
<style>
.wrapper {
margin-block: 1em;
}
.bars {
height: 20px;
display: flex;
}
.bar {
height: 100%;
color: black;
display: flex;
align-items: center;
font-size: 0.8em;
padding-left: 0.4em;
}
</style>

View File

@@ -4,6 +4,7 @@
import { Checkbox } from "@nodes/ui";
import localStore from "$lib/helpers/localStore";
import { type PerformanceData } from "./store";
import BarSplit from "./BarSplit.svelte";
export let data: PerformanceData;
@@ -42,7 +43,7 @@
}
function getLast(key: string) {
return data.at(-1)?.[key][0] || 0;
return data.at(-1)?.[key]?.[0] || 0;
}
function getLasts() {
@@ -53,13 +54,13 @@
if (onlyLast) {
return (
getLast("runtime") +
getLast("create-geometries") +
getLast("update-geometries") +
getLast("worker-transfer")
);
}
return (
getAverage("runtime") +
getAverage("create-geometries") +
getAverage("update-geometries") +
getAverage("worker-transfer")
);
}
@@ -73,7 +74,7 @@
const viewerKeys = [
"total-vertices",
"total-faces",
"create-geometries",
"update-geometries",
"split-result",
];
@@ -116,8 +117,8 @@
return data.map((run) => {
return (
run["runtime"].reduce((acc, v) => acc + v, 0) +
run["create-geometries"].reduce((acc, v) => acc + v, 0) +
run["worker-transfer"].reduce((acc, v) => acc + v, 0)
run["update-geometries"].reduce((acc, v) => acc + v, 0) +
(run["worker-transfer"]?.reduce((acc, v) => acc + v, 0) || 0)
);
});
}
@@ -125,8 +126,8 @@
return data.map((run) => {
return (
run["runtime"][0] +
run["create-geometries"][0] +
run["worker-transfer"][0]
run["update-geometries"][0] +
(run["worker-transfer"]?.[0] || 0)
);
});
}
@@ -147,6 +148,22 @@
});
}
function getSplitValues(): number[] {
if (showAverage) {
return [
getAverage("worker-transfer"),
getAverage("runtime"),
getAverage("update-geometries"),
];
}
return [
getLast("worker-transfer"),
getLast("runtime"),
getLast("update-geometries"),
];
}
function getTitle(t: string) {
if (t.includes("/")) {
return `Node ${t.split("/").slice(-1).join("/")}`;
@@ -159,7 +176,7 @@
}
</script>
{#key $activeType && data}
{#key $activeType}
{#if $activeType === "cache-hit"}
<Monitor
title="Cache Hits"
@@ -174,117 +191,122 @@
points={constructPoints($activeType)}
/>
{/if}
<div class="p-4">
<div class="flex items-center gap-2">
<Checkbox id="show-total" bind:value={showAverage} />
<label for="show-total">Show Average</label>
</div>
{#if data.length !== 0}
<h3>General</h3>
<table>
<tbody>
<tr>
<td>
{round(getTotalPerformance(!showAverage))}<span>ms</span>
</td>
<td
class:active={$activeType === "total"}
on:click={() => ($activeType = "total")}
>
total<span
>({Math.floor(
1000 / getTotalPerformance(showAverage),
)}fps)</span
>
</td>
</tr>
{#each getPerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key}
</td>
</tr>
{/each}
<tr>
<td>{data.length}</td>
<td>Samples</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
<h3>Nodes</h3>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td> {getCacheRatio(!showAverage)}<span>%</span> </td>
<td
class:active={$activeType === "cache-hit"}
on:click={() => ($activeType = "cache-hit")}>cache hits</td
>
</tr>
{#each getNodePerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
<tbody>
<tr>
<td>
<h3>Viewer</h3>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>{humanizeNumber(getLast("total-vertices"))}</td>
<td>Vertices</td>
</tr>
<tr>
<td>{humanizeNumber(getLast("total-faces"))}</td>
<td>Faces</td>
</tr>
{#each getViewerPerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
</table>
{:else}
<p>No runs available</p>
{/if}
</div>
{/key}
<div class="p-4 performance-tabler">
<div class="flex items-center gap-2">
<Checkbox id="show-total" bind:value={showAverage} />
<label for="show-total">Show Average</label>
</div>
{#if data.length !== 0}
<BarSplit
labels={["worker-transfer", "runtime", "update-geometries"]}
values={getSplitValues()}
/>
<h3>General</h3>
<table>
<tbody>
<tr>
<td>
{round(getTotalPerformance(!showAverage))}<span>ms</span>
</td>
<td
class:active={$activeType === "total"}
on:click={() => ($activeType = "total")}
>
total<span
>({Math.floor(1000 / getTotalPerformance(showAverage))}fps)</span
>
</td>
</tr>
{#each getPerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key}
</td>
</tr>
{/each}
<tr>
<td>{data.length}</td>
<td>Samples</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
<h3>Nodes</h3>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td> {getCacheRatio(!showAverage)}<span>%</span> </td>
<td
class:active={$activeType === "cache-hit"}
on:click={() => ($activeType = "cache-hit")}>cache hits</td
>
</tr>
{#each getNodePerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
<tbody>
<tr>
<td>
<h3>Viewer</h3>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>{humanizeNumber(getLast("total-vertices"))}</td>
<td>Vertices</td>
</tr>
<tr>
<td>{humanizeNumber(getLast("total-faces"))}</td>
<td>Faces</td>
</tr>
{#each getViewerPerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
</table>
{:else}
<p>No runs available</p>
{/if}
</div>
<style>
h3 {
margin: 0;
@@ -296,6 +318,9 @@
opacity: 0.3;
margin-left: 4px;
}
table {
margin-bottom: 70px;
}
td {
padding-right: 10px;
padding-block: 5px;

View File

@@ -6,15 +6,18 @@ export interface PerformanceStore extends Readable<PerformanceData> {
startRun(): void;
stopRun(): void;
addPoint(name: string, value?: number): void;
endPoint(name?: string): void;
mergeData(data: PerformanceData[number]): void;
get: () => PerformanceData;
}
export function createPerformanceStore(): PerformanceStore {
export function createPerformanceStore(id?: string): PerformanceStore {
let data: PerformanceData = [];
let currentRun: Record<string, number[]> | undefined;
let temp: Record<string, number> | undefined;
let lastPoint: string | undefined;
let set: (v: PerformanceData) => void;
@@ -23,22 +26,36 @@ export function createPerformanceStore(): PerformanceStore {
});
function startRun() {
if (currentRun) return;
currentRun = {};
lastPoint = undefined;
temp = {
start: performance.now()
}
}
function stopRun() {
if (currentRun) {
if (currentRun && temp) {
currentRun["total"] = [performance.now() - temp.start];
data.push(currentRun);
data = data.slice(-100);
currentRun = undefined;
temp = undefined;
if (set) set(data);
}
}
function addPoint(name: string, value: number) {
function addPoint(name: string, value?: number) {
if (!currentRun) return;
currentRun[name] = currentRun[name] || [];
currentRun[name].push(value);
if (value === undefined) {
if (temp) {
lastPoint = name;
temp[name] = performance.now();
}
} else {
currentRun[name] = currentRun[name] || [];
currentRun[name].push(value);
}
}
function get() {
@@ -59,11 +76,21 @@ export function createPerformanceStore(): PerformanceStore {
});
}
function endPoint(name = lastPoint) {
if (name === lastPoint) lastPoint = undefined;
if (name && currentRun && temp && name in temp) {
currentRun[name] = currentRun[name] || [];
currentRun[name].push(performance.now() - temp[name]);
delete temp[name];
}
}
return {
subscribe,
startRun,
stopRun,
addPoint,
endPoint,
mergeData,
get
}