47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
16:54Stealth Union Alpha: Is this another cheap GPT model? (better than Luna, cheaper than Terra?)
Sep 16, 2026 · YouTube
16:45DeepSeek V4.1 Flash Is Shockingly Good for the Price
Sep 10, 2026 · YouTube
17:14How much better is GPT-6 Astra over Claude Opus 5? Real Website and Coding Tests
Sep 5, 2026 · YouTube
29:13Implementing a multiplayer game with GPT-6 Astra (+ Gemini 3.8, Opus 5, Sol Pro)
Sep 5, 2026 · YouTube
19:42Meta Muse Spark 1.3 Review: A Huge Leap Forward
Sep 2, 2026 · YouTube
17:31Testing Gemini 3.8 Flash on Real Coding Challenges (vs. other models)
Sep 2, 2026 · YouTube
You are a graphics engineer who has spent a lot of time finding out why things are slow.
I want a hundred thousand things moving on screen at sixty frames a second, in one HTML file, with no libraries.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file. Your data layout, your draw strategy, and the one thing you expect to be the bottleneck.
The single fenced html block.
This is the section I care most about. Be specific and commit to numbers:
If you could not do 100,000 at 60fps and shipped fewer, or a cheaper effect than a real flow field, say so here, plainly, and say what you shipped instead. Write Nothing dropped. if you delivered the brief in full.
I am going to open the file and read the FPS counter.
Then I am going to compare it against your prediction. A model that says "about 45fps, fill-rate bound" and measures 43 has understood its own code. A model that says 60 and measures 4 has not, however elegant the code is — and that gap is most of what I am testing here. An honest prediction of a mediocre number beats a confident prediction of a good one.
I'll use a single Float32Array for particle state (x, y, vx, vy) and a 64×64 precomputed flow-field grid of vectors, updated each frame with a few sine/cosine terms. Particles are updated on the CPU with bilinear sampling of the flow field, then plotted as single pixels into a Uint32Array view of an ImageData buffer. The buffer is faded each frame with a per-channel lookup table to create trails, then putImageData draws it. The bottleneck will be the CPU particle update loop (100k iterations with bilinear interpolation and bounds checks), followed by the fade loop and putImageData.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
html, body {
margin: 0;
padding: 0;
background: #000;
overflow: hidden;
height: 100%;
}
canvas {
display: block;
margin: 0 auto;
background: #000;
}
#fps, #count {
position: absolute;
top: 10px;
color: #fff;
font: 14px monospace;
text-shadow: 0 0 4px #000;
z-index: 10;
pointer-events: none;
}
#fps { left: 10px; }
#count { left: 120px; }
</style>
</head>
<body>
<canvas id="c" width="900" height="600"></canvas>
<div id="fps">FPS: --</div>
<div id="count">Particles: --</div>
<script>
(function() {
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d', { alpha: false });
const W = 900, H = 600;
const N = 100000;
const GRID = 64;
const particles = new Float32Array(N * 4);
for (let i = 0; i < N; i++) {
const idx = i * 4;
particles[idx] = Math.random() * W;
particles[idx+1] = Math.random() * H;
particles[idx+2] = 0;
particles[idx+3] = 0;
}
const flowX = new Float32Array(GRID * GRID);
const flowY = new Float32Array(GRID * GRID);
const imageData = ctx.createImageData(W, H);
const data = new Uint32Array(imageData.data.buffer);
data.fill(0xFF000000);
ctx.putImageData(imageData, 0, 0);
const fadeTable = new Uint8Array(256);
for (let i = 0; i < 256; i++) {
fadeTable[i] = i - (i >> 5);
}
const fpsEl = document.getElementById('fps');
const countEl = document.getElementById('count');
countEl.textContent = 'Particles: ' + (particles.length / 4);
let lastTime = performance.now();
let fpsAccum = 0;
let fpsFrames = 0;
let fps = 0;
function updateFlow(t) {
let idx = 0;
const driftX = Math.sin(t * 0.3) * 0.3;
const driftY = Math.cos(t * 0.4) * 0.3;
for (let y = 0; y < GRID; y++) {
for (let x = 0; x < GRID; x++) {
const angle = Math.sin(x * 0.08 + t * 0.5) +
Math.cos(y * 0.06 + t * 0.7) +
Math.sin((x + y) * 0.04 + t * 1.1) +
Math.cos((x - y) * 0.05 + t * 0.9);
flowX[idx] = Math.cos(angle) + driftX;
flowY[idx] = Math.sin(angle) + driftY;
idx++;
}
}
}
function updateParticles() {
const scaleX = GRID / W;
const scaleY = GRID / H;
const speed = 2.0;
const inertia = 0.96;
const flowInfluence = 0.04;
for (let i = 0; i < N; i++) {
const idx = i * 4;
let x = particles[idx];
let y = particles[idx+1];
let vx = particles[idx+2];
let vy = particles[idx+3];
let gx = x * scaleX;
let gy = y * scaleY;
let ix = gx | 0;
let iy = gy | 0;
if (ix < 0) ix = 0; else if (ix > GRID - 2) ix = GRID - 2;
if (iy < 0) iy = 0; else if (iy > GRID - 2) iy = GRID - 2;
const fx = gx - ix;
const fy = gy - iy;
const i00 = iy * GRID + ix;
const i10 = i00 + 1;
const i01 = i00 + GRID;
const i11 = i01 + 1;
const v00x = flowX[i00], v00y = flowY[i00];
const v10x = flowX[i10], v10y = flowY[i10];
const v01x = flowX[i01], v01y = flowY[i01];
const v11x = flowX[i11], v11y = flowY[i11];
const vx0 = v00x + (v10x - v00x) * fx;
const vy0 = v00y + (v10y - v00y) * fx;
const vx1 = v01x + (v11x - v01x) * fx;
const vy1 = v01y + (v11y - v01y) * fx;
const flowXVal = vx0 + (vx1 - vx0) * fy;
const flowYVal = vy0 + (vy1 - vy0) * fy;
vx = vx * inertia + flowXVal * flowInfluence;
vy = vy * inertia + flowYVal * flowInfluence;
x += vx * speed;
y += vy * speed;
if (x < 0 || x >= W || y < 0 || y >= H) {
x = Math.random() * W;
y = Math.random() * H;
vx = 0;
vy = 0;
}
particles[idx] = x;
particles[idx+1] = y;
particles[idx+2] = vx;
particles[idx+3] = vy;
const px = x | 0;
const py = y | 0;
const pixelIndex = py * W + px;
data[pixelIndex] = 0xFFFFFFFF;
}
}
function animate(now) {
requestAnimationFrame(animate);
const dt = now - lastTime;
lastTime = now;
fpsAccum += dt;
fpsFrames++;
if (fpsFrames >= 30) {
fps = 1000 / (fpsAccum / fpsFrames);
fpsAccum = 0;
fpsFrames = 0;
fpsEl.textContent = 'FPS: ' + fps.toFixed(1);
}
const t = now * 0.001;
updateFlow(t);
for (let i = 0; i < data.length; i++) {
const v = data[i];
const r = v & 0xFF;
const g = (v >> 8) & 0xFF;
const b = (v >> 16) & 0xFF;
data[i] = 0xFF000000 | (fadeTable[b] << 16) | (fadeTable[g] << 8) | fadeTable[r];
}
updateParticles();
ctx.putImageData(imageData, 0, 0);
}
requestAnimationFrame(animate);
})();
</script>
</body>
</html>
requestAnimationFrame). The actual frame time will be around 8–12 ms, so it will comfortably hit 60 fps.putImageData are the draw costs. The flow-field update is minor.putImageData) remains constant, but plotting 1M pixels adds some cost. The bottleneck is the per-particle CPU work.Nothing dropped.