Last active
June 11, 2026 11:13
-
-
Save peebeebee/ab93aed91b71aa1a3f1f62961804e183 to your computer and use it in GitHub Desktop.
Browser Paint stresstest
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> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <title>DOM Stress Test (Auto)</title> | |
| <style> | |
| body { | |
| margin: 0; | |
| font-family: monospace; | |
| overflow: hidden; | |
| } | |
| #grid { | |
| display: flex; | |
| flex-wrap: wrap; | |
| padding-top: 40px; | |
| } | |
| #controls { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| background: #111; | |
| color: #0f0; | |
| padding: 6px; | |
| z-index: 10; | |
| } | |
| .box { | |
| width: 18px; | |
| height: 18px; | |
| margin: 1px; | |
| background: red; | |
| opacity: 0.85; | |
| will-change: transform; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="controls"> | |
| <span id="stats">starting...</span> | |
| </div> | |
| <div id="grid"></div> | |
| <script> | |
| const MAX_BOXES = 1000; | |
| const grid = document.getElementById("grid"); | |
| const stats = document.getElementById("stats"); | |
| let boxes = []; | |
| let frame = 0; | |
| function rand(n) { | |
| return (Math.random() * n) | 0; | |
| } | |
| function createBox() { | |
| const el = document.createElement("div"); | |
| el.className = "box"; | |
| el.style.background = `hsl(${rand(360)}, 80%, 50%)`; | |
| grid.appendChild(el); | |
| boxes.push(el); | |
| } | |
| function removeBox() { | |
| if (!boxes.length) return; | |
| const i = rand(boxes.length); | |
| const el = boxes[i]; | |
| el.remove(); | |
| boxes.splice(i, 1); | |
| } | |
| function mutateBox() { | |
| if (!boxes.length) return; | |
| const el = boxes[rand(boxes.length)]; | |
| // layout read (forces reflow) | |
| const w = el.offsetWidth; | |
| const h = el.offsetHeight; | |
| // layout write | |
| el.style.width = (w + (rand(3) - 1)) + "px"; | |
| el.style.height = (h + (rand(3) - 1)) + "px"; | |
| el.style.transform = | |
| `translate(${rand(8)}px, ${rand(8)}px) rotate(${rand(360)}deg)`; | |
| } | |
| function layoutThrash() { | |
| let sum = 0; | |
| for (let i = 0; i < boxes.length; i++) { | |
| const el = boxes[i]; | |
| el.style.marginLeft = (i % 6) + "px"; | |
| // forced layout read | |
| sum += el.offsetHeight; | |
| } | |
| return sum; | |
| } | |
| function shuffleDom() { | |
| const len = grid.children.length; | |
| for (let i = 0; i < len; i++) { | |
| const a = rand(len); | |
| const b = grid.children[a]; | |
| if (b) grid.appendChild(b); | |
| } | |
| } | |
| function fillInitial() { | |
| for (let i = 0; i < MAX_BOXES; i++) { | |
| createBox(); | |
| } | |
| } | |
| function tick() { | |
| // keep at ~1000 boxes | |
| while (boxes.length < MAX_BOXES) createBox(); | |
| while (boxes.length > MAX_BOXES) removeBox(); | |
| // heavy mutation burst | |
| for (let i = 0; i < 80; i++) mutateBox(); | |
| for (let i = 0; i < 20; i++) if (Math.random() > 0.5) removeBox(); | |
| if (Math.random() > 0.4) shuffleDom(); | |
| const sum = layoutThrash(); | |
| stats.textContent = | |
| `boxes=${boxes.length} frame=${frame} layoutSum=${sum}`; | |
| frame++; | |
| requestAnimationFrame(tick); | |
| } | |
| // auto start | |
| fillInitial(); | |
| tick(); | |
| </script> | |
| </body> | |
| </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> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>GPU Paint Stress Test</title> | |
| <style> | |
| html, body { | |
| margin: 0; | |
| width: 100%; | |
| height: 100%; | |
| overflow: hidden; | |
| background: #000; | |
| } | |
| .grid { | |
| width: 100vw; | |
| height: 100vh; | |
| display: grid; | |
| grid-template-columns: repeat(20, 1fr); | |
| gap: 2px; | |
| animation: zoomRotate 12s linear infinite alternate; | |
| transform-origin: center center; | |
| will-change: transform; | |
| } | |
| .cell { | |
| aspect-ratio: 1; | |
| overflow: hidden; | |
| contain: paint; | |
| } | |
| .cell img { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| display: block; | |
| transform: translateZ(0); | |
| backface-visibility: hidden; | |
| will-change: transform; | |
| } | |
| @keyframes zoomRotate { | |
| 0% { transform: scale(1) rotate(0deg); } | |
| 100% { transform: scale(1.08) rotate(1deg); } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="grid" id="grid"></div> | |
| <script> | |
| const grid = document.getElementById("grid"); | |
| const gifs = [ | |
| "https://media.tenor.com/On7kvXhzml4AAAAj/loading-gif.gif", | |
| "https://media.tenor.com/wP4KiKYK0aUAAAAC/bill-hicks-mic-tap.gif", | |
| "https://media.tenor.com/qJ5evVs-_uUAAAAC/cat-funny.gif" | |
| ]; | |
| const COUNT = 400; // 20x20 | |
| for (let i = 0; i < COUNT; i++) { | |
| const cell = document.createElement("div"); | |
| cell.className = "cell"; | |
| const img = document.createElement("img"); | |
| img.src = gifs[i % gifs.length] + "?v=" + i; | |
| cell.appendChild(img); | |
| grid.appendChild(cell); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment