Last active
August 21, 2026 16:40
-
-
Save jogibear9988/eb36095c7f06ee22e7dd665ff151f9cb to your computer and use it in GitHub Desktop.
getboxquads-optimization-stage-benchmark.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>GeometryUtils optimization stage benchmark</title> | |
| <style> | |
| body { font: 14px sans-serif; margin: 20px; } | |
| #results { white-space: pre-wrap; } | |
| #fixture { contain: layout style paint; } | |
| </style> | |
| <div id="fixture"></div> | |
| <pre id="results">ready</pre> | |
| <script> | |
| 'use strict'; | |
| const params = new URL(location.href).searchParams; | |
| const scenarioName = params.get('scenario') || 'geometry'; | |
| const fixture = document.querySelector('#fixture'); | |
| const results = document.querySelector('#results'); | |
| const svgNamespace = 'http://www.w3.org/2000/svg'; | |
| function createGeometryScenario() { | |
| const canvas = document.createElement('div'); | |
| fixture.appendChild(canvas); | |
| let host = canvas; | |
| for (let depth = 0; depth < 6; ++depth) { | |
| const shadowHost = document.createElement('div'); | |
| host.appendChild(shadowHost); | |
| host = shadowHost.attachShadow({mode: 'open'}); | |
| } | |
| const targets = []; | |
| const fragment = document.createDocumentFragment(); | |
| for (let index = 0; index < 1200; ++index) { | |
| const target = document.createElement('div'); | |
| target.style.cssText = | |
| `position:absolute;left:${index % 60}px;top:${index % 40}px;` + | |
| 'width:10px;height:8px;transform:rotate(0.2deg)'; | |
| fragment.appendChild(target); | |
| targets.push(target); | |
| } | |
| host.appendChild(fragment); | |
| document.body.offsetTop; | |
| if (typeof targets[0].getBoxQuads !== 'function') { | |
| throw new Error('GeometryUtils is not enabled'); | |
| } | |
| return () => { | |
| let checksum = 0; | |
| for (const target of targets) { | |
| checksum += target.getBoxQuads({relativeTo: canvas})[0].p3.x; | |
| } | |
| return checksum; | |
| }; | |
| } | |
| function appendTree(parent, branchCount, depth) { | |
| const fragment = document.createDocumentFragment(); | |
| for (let branch = 0; branch < branchCount; ++branch) { | |
| let node = document.createElement('div'); | |
| fragment.appendChild(node); | |
| for (let level = 0; level < depth; ++level) { | |
| const child = document.createElement('div'); | |
| node.appendChild(child); | |
| node = child; | |
| } | |
| } | |
| parent.appendChild(fragment); | |
| } | |
| function createTraversalScenario() { | |
| const style = document.createElement('style'); | |
| style.textContent = | |
| '.changed-a{color:rgb(10,20,30)}.changed-b{color:rgb(30,20,10)}'; | |
| document.head.appendChild(style); | |
| const tree = document.createElement('div'); | |
| const scope = document.createElement('div'); | |
| tree.appendChild(scope); | |
| fixture.appendChild(tree); | |
| appendTree(tree, 1500, 4); | |
| appendTree(scope, 40, 6); | |
| let sharedParent = scope.children[6]; | |
| while (sharedParent.firstElementChild) { | |
| sharedParent = sharedParent.firstElementChild; | |
| } | |
| const nestedTargetA = document.createElement('div'); | |
| const nestedTargetB = document.createElement('div'); | |
| sharedParent.append(nestedTargetA, nestedTargetB); | |
| const targets = [ | |
| scope.children[4].lastElementChild, | |
| scope.children[5].lastElementChild, | |
| nestedTargetA, | |
| nestedTargetB, | |
| ]; | |
| let phase = false; | |
| document.body.offsetTop; | |
| return () => { | |
| phase = !phase; | |
| const className = phase ? 'changed-a' : 'changed-b'; | |
| for (const target of targets) target.className = className; | |
| return getComputedStyle(targets[3]).color.length; | |
| }; | |
| } | |
| function createPresentationScenario() { | |
| const svg = document.createElementNS(svgNamespace, 'svg'); | |
| fixture.appendChild(svg); | |
| const fragment = document.createDocumentFragment(); | |
| const elements = []; | |
| for (let index = 0; index < 2500; ++index) { | |
| const rect = document.createElementNS(svgNamespace, 'rect'); | |
| rect.setAttribute('x', index % 100); | |
| rect.setAttribute('y', Math.floor(index / 100)); | |
| rect.setAttribute('width', '1'); | |
| rect.setAttribute('height', '1'); | |
| rect.setAttribute('opacity', '0.4'); | |
| fragment.appendChild(rect); | |
| elements.push(rect); | |
| } | |
| svg.appendChild(fragment); | |
| let phase = false; | |
| document.body.offsetTop; | |
| return () => { | |
| phase = !phase; | |
| const opacity = phase ? '0.4' : '0.6'; | |
| for (const element of elements) element.setAttribute('opacity', opacity); | |
| return Number(getComputedStyle(elements.at(-1)).opacity); | |
| }; | |
| } | |
| function createSvgLayoutScenario() { | |
| const svg = document.createElementNS(svgNamespace, 'svg'); | |
| const group = document.createElementNS(svgNamespace, 'g'); | |
| svg.appendChild(group); | |
| fixture.appendChild(svg); | |
| const fragment = document.createDocumentFragment(); | |
| const elements = []; | |
| for (let index = 0; index < 3000; ++index) { | |
| const rect = document.createElementNS(svgNamespace, 'rect'); | |
| rect.setAttribute('x', index * 2); | |
| rect.setAttribute('y', '0'); | |
| rect.setAttribute('width', '1'); | |
| rect.setAttribute('height', '10'); | |
| fragment.appendChild(rect); | |
| elements.push(rect); | |
| } | |
| group.appendChild(fragment); | |
| const targets = []; | |
| for (let index = 500; index < 600; index += 10) { | |
| targets.push(elements[index]); | |
| } | |
| let phase = false; | |
| document.body.offsetTop; | |
| return () => { | |
| phase = !phase; | |
| const offset = phase ? 0.25 : 0.5; | |
| for (let index = 0; index < targets.length; ++index) { | |
| targets[index].setAttribute('x', 1000 + index * 20 + offset); | |
| } | |
| return group.getBBox().width; | |
| }; | |
| } | |
| const factories = { | |
| geometry: createGeometryScenario, | |
| traversal: createTraversalScenario, | |
| presentation: createPresentationScenario, | |
| 'svg-layout': createSvgLayoutScenario, | |
| }; | |
| let operation; | |
| try { | |
| operation = factories[scenarioName](); | |
| } catch (error) { | |
| window.__optimizationBenchmarkError = error.stack || String(error); | |
| results.textContent = window.__optimizationBenchmarkError; | |
| throw error; | |
| } | |
| async function measure(durationMs) { | |
| const samples = []; | |
| let operations = 0; | |
| let checksum = 0; | |
| const start = performance.now(); | |
| while (performance.now() - start < durationMs) { | |
| const batchStart = performance.now(); | |
| checksum += operation(); | |
| samples.push(performance.now() - batchStart); | |
| ++operations; | |
| if (operations % 20 === 0) { | |
| await new Promise(resolve => setTimeout(resolve, 0)); | |
| } | |
| } | |
| const elapsedMs = performance.now() - start; | |
| samples.sort((a, b) => a - b); | |
| const percentile = value => | |
| samples[Math.min(samples.length - 1, | |
| Math.floor(samples.length * value))]; | |
| return { | |
| operations, | |
| elapsedMs, | |
| operationsPerSecond: operations * 1000 / elapsedMs, | |
| operationMs: { | |
| average: samples.reduce((sum, value) => sum + value, 0) / samples.length, | |
| p50: percentile(0.5), | |
| p95: percentile(0.95), | |
| }, | |
| checksum, | |
| }; | |
| } | |
| window.__optimizationBenchmarkReady = true; | |
| window.__runOptimizationBenchmark = async function() { | |
| await measure(1000); | |
| const measurement = await measure(5000); | |
| const result = { | |
| scenario: scenarioName, | |
| browser: navigator.userAgent, | |
| measurement, | |
| }; | |
| window.__optimizationBenchmarkResult = result; | |
| results.textContent = JSON.stringify(result, null, 2); | |
| return result; | |
| }; | |
| if (params.get('autorun') === '1') window.__runOptimizationBenchmark(); | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment