From bccbcc12c72f5edde605601a311646d1ca96d7e1 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Thu, 31 Jul 2025 16:04:04 +0100 Subject: Add CPU performance benchmarking --- src/ui/benchmarkView.ts | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/ui/benchmarkView.ts (limited to 'src/ui/benchmarkView.ts') diff --git a/src/ui/benchmarkView.ts b/src/ui/benchmarkView.ts new file mode 100644 index 0000000..487ec63 --- /dev/null +++ b/src/ui/benchmarkView.ts @@ -0,0 +1,111 @@ +import {ChunkAllocationMode, RaytraceContext, RaytracerOptions} from "../models/RaytraceContext"; +import {RaytraceDispatcher} from "../RaytraceDispatcher"; +import {Framebuffer} from "../Framebuffer"; +import {getScene} from "../models/Scene"; +import {Colour} from "../models/Colour"; +import {Logger} from "../Logger"; +import * as BenchmarkChart from "./benchmarkCharts"; + +let multiCoreDispatcher: RaytraceDispatcher; +let singleCoreDispatcher: RaytraceDispatcher; + +let multiCoreScore = 0; +let singleCoreScore = 0; + +const deviceAvailableThreadCount = navigator.hardwareConcurrency; + +const logger = new Logger(document.getElementById('console-benchmark')!); + +const benchmarkButton = document.getElementById('benchmark')!; +const multiCoreScoreElement = document.getElementById('multi-core-score')!; +const singleCoreScoreElement = document.getElementById('single-core-score')!; + +export function registerEventListeners() { + benchmarkButton.addEventListener('click', startBenchmark); + logger.log(`Detected ${deviceAvailableThreadCount} available CPU threads, ready to run`); +} + +export function initChart() { + BenchmarkChart.initScoreChart(document.getElementById('benchmark-results-graph')!); +} + +function startBenchmark() { + benchmarkButton.classList.add('loading'); + multiCoreScoreElement.classList.add('loading'); + document.getElementById('single-core-score')!.classList.add('loading'); + + multiCoreDispatcher = initDispatcher( + 1920, + 1080, + getBenchmarkRenderOptions(true), + onMultiCoreBenchmarkComplete + ) + + singleCoreDispatcher = initDispatcher( + 1920, + 1080, + getBenchmarkRenderOptions(false), + onSingleCoreBenchmarkComplete + ) + + logger.log("Started multi-core benchmark"); + multiCoreDispatcher.requestRender(); +} + +function onMultiCoreBenchmarkComplete(score: number) { + multiCoreScore = score; + multiCoreScoreElement.textContent = `${multiCoreScore}`; + multiCoreScoreElement.classList.remove('loading'); + logger.log("Started single core benchmark"); + singleCoreDispatcher.requestRender(); +} + +function onSingleCoreBenchmarkComplete(score: number) { + singleCoreScore = score; + benchmarkButton.classList.remove('loading'); + singleCoreScoreElement.textContent = `${singleCoreScore}`; + singleCoreScoreElement.classList.remove('loading'); + + BenchmarkChart.addDeviceResult(multiCoreScore, singleCoreScore); +} + +function initDispatcher(width: number, height: number, options: RaytracerOptions, onComplete: Function): RaytraceDispatcher { + const fov = Math.PI / 3; + const framebuffer = new Framebuffer(width, height); + + const {spheres, planes, lights} = getScene(); + + const context = new RaytraceContext( + height, + width, + fov, + spheres, + planes, + lights, + new Colour(221, 221, 221), + options + ); + + return new RaytraceDispatcher( + framebuffer, + context, + logger, + onComplete + ); +} + +function getBenchmarkRenderOptions(multiCore: boolean) { + return { + numThreads: multiCore ? deviceAvailableThreadCount: 1, + shadows: true, + diffuseLighting: true, + specularLighting: true, + reflections: true, + refractions: true, + maxRecurseDepth: 5, + maxDrawDistance: 1000, + directMemoryTransfer: true, + chunkSize: 0, + chunkAllocationMode: ChunkAllocationMode.SEQUENTIAL + } +} -- cgit v1.2.3