Spaces:
Running
Running
| <html lang="en" data-theme="light"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta name="color-scheme" content="light dark"> | |
| <script>(function(){var s=localStorage.getItem('theme');if(!s){s=(window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches)?'dark':'light';}document.documentElement.setAttribute('data-theme',s);})();</script> | |
| <title>WebGPU Bench</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="css/style.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script> | |
| </head> | |
| <body> | |
| <header class="header"> | |
| <div class="header-inner"> | |
| <a href="/" class="header-brand"> | |
| <svg class="header-logo" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="1" x2="9" y2="4"/><line x1="15" y1="1" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="23"/><line x1="15" y1="20" x2="15" y2="23"/><line x1="20" y1="9" x2="23" y2="9"/><line x1="20" y1="14" x2="23" y2="14"/><line x1="1" y1="9" x2="4" y2="9"/><line x1="1" y1="14" x2="4" y2="14"/></svg> | |
| <span class="header-title">WebGPU Bench</span> | |
| </a> | |
| <nav class="header-nav" aria-label="Primary"> | |
| <a href="run.html" class="header-link">Run</a> | |
| <a href="methodology.html" class="header-link">Methodology</a> | |
| <button id="theme-toggle" class="header-link theme-toggle-btn" type="button" title="Toggle theme" aria-label="Toggle dark mode"> | |
| <svg class="icon-sun" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg> | |
| <svg class="icon-moon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg> | |
| </button> | |
| <a href="https://github.com/abhijitramesh/webgpu-bench" target="_blank" rel="noopener" class="header-link"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.44 9.8 8.2 11.39.6.11.82-.26.82-.58v-2.03c-3.34.73-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.74.08-.73.08-.73 1.2.09 1.84 1.24 1.84 1.24 1.07 1.83 2.81 1.3 3.5 1 .11-.78.42-1.3.76-1.6-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.13-.3-.54-1.52.12-3.18 0 0 1.01-.32 3.3 1.23a11.5 11.5 0 0 1 6.02 0c2.28-1.55 3.29-1.23 3.29-1.23.66 1.66.25 2.88.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.81 5.63-5.48 5.92.43.37.81 1.1.81 2.22v3.29c0 .32.22.7.82.58C20.57 21.8 24 17.3 24 12c0-6.63-5.37-12-12-12z"/></svg> | |
| GitHub | |
| </a> | |
| </nav> | |
| </div> | |
| </header> | |
| <main> | |
| <div id="loading" aria-busy="true" aria-label="Loading benchmark data"> | |
| <div class="skeleton skeleton-hero" aria-hidden="true"></div> | |
| <div class="skeleton skeleton-filters" aria-hidden="true"></div> | |
| <div class="skeleton-stats" aria-hidden="true"> | |
| <div class="skeleton"></div> | |
| <div class="skeleton"></div> | |
| <div class="skeleton"></div> | |
| </div> | |
| <div class="skeleton skeleton-table" aria-hidden="true"></div> | |
| </div> | |
| <div id="dashboard" style="display: none;"> | |
| <!-- Hero --> | |
| <section class="hero"> | |
| <div class="container hero-inner"> | |
| <div class="hero-copy"> | |
| <span class="hero-eyebrow" id="hero-live" hidden> | |
| <span class="hero-eyebrow-dot" aria-hidden="true"></span> | |
| <span id="hero-live-text">Live</span> | |
| </span> | |
| <h1 class="hero-title">WebGPU Bench</h1> | |
| <p class="hero-lede">Real-browser benchmarks for <code>llama.cpp</code>'s WebGPU backend. GGUF models loaded via WebAssembly, measured across Chrome and Safari.</p> | |
| <p class="hero-meta" id="hero-meta" hidden></p> | |
| <div class="hero-actions"> | |
| <a href="run.html" class="btn btn-primary">Run on your machine</a> | |
| <a href="methodology.html" class="btn btn-secondary">Methodology</a> | |
| </div> | |
| </div> | |
| <aside class="hero-stat" id="hero-stat" aria-live="polite" hidden> | |
| <span class="hero-stat-label">Top decode</span> | |
| <span class="hero-stat-value"> | |
| <span class="hero-stat-num" id="hero-top-decode" data-target="0">0.0</span> | |
| <span class="hero-stat-unit">tok/s</span> | |
| </span> | |
| <span class="hero-stat-meta" id="hero-top-meta">—</span> | |
| </aside> | |
| </div> | |
| </section> | |
| <!-- Sticky head: filter bar + section jump links --> | |
| <div class="sticky-head"> | |
| <!-- Filter Bar --> | |
| <div class="filter-bar"> | |
| <div class="filter-bar-inner"> | |
| <div class="filter-group"> | |
| <label class="filter-label" for="filter-machine">Machine</label> | |
| <select id="filter-machine" class="filter-select"></select> | |
| </div> | |
| <div class="filter-group"> | |
| <label class="filter-label" for="filter-browser">Browser</label> | |
| <select id="filter-browser" class="filter-select"></select> | |
| </div> | |
| <div class="filter-group"> | |
| <label class="filter-label" for="filter-model">Model</label> | |
| <select id="filter-model" class="filter-select"></select> | |
| </div> | |
| <div class="filter-group"> | |
| <label class="filter-label" for="filter-backend">Backend</label> | |
| <select id="filter-backend" class="filter-select"></select> | |
| </div> | |
| <div class="filter-group"> | |
| <label class="filter-label" for="filter-status">Status</label> | |
| <select id="filter-status" class="filter-select"></select> | |
| </div> | |
| <div class="filter-group"> | |
| <label class="filter-label">Quantization</label> | |
| <div class="quant-dropdown" id="quant-dropdown"> | |
| <button class="quant-dropdown-btn" id="quant-dropdown-btn" type="button"> | |
| <span id="quant-dropdown-text">All Quants</span> | |
| <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg> | |
| </button> | |
| <div class="quant-dropdown-list" id="quant-options"></div> | |
| </div> | |
| </div> | |
| <div class="filter-actions"> | |
| <button class="filter-reset-btn" id="filter-reset" type="button" disabled title="Reset all filters"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg> | |
| <span class="filter-reset-label">Reset</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section Navigation --> | |
| <nav class="section-nav" id="section-nav" aria-label="Dashboard sections"> | |
| <div class="section-nav-track"> | |
| <button class="section-nav-item active" data-section="overview">Overview</button> | |
| <button class="section-nav-item" data-section="results-section">Results</button> | |
| <button class="section-nav-item" data-section="performance-section">Performance</button> | |
| <button class="section-nav-item" data-section="errors-section">Errors</button> | |
| <button class="section-nav-item" data-section="machines-section">Machines</button> | |
| </div> | |
| </nav> | |
| </div><!-- /sticky-head --> | |
| <!-- Overview --> | |
| <section id="overview" class="dash-section"> | |
| <div class="container"> | |
| <div class="summary-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon stat-card-icon--machines"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg> | |
| </div> | |
| <div class="stat-card-content"> | |
| <span class="stat-card-label">Machines</span> | |
| <span class="stat-card-value" id="stat-machines" data-target="0">0</span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon stat-card-icon--benchmarks"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg> | |
| </div> | |
| <div class="stat-card-content"> | |
| <span class="stat-card-label">Benchmarks</span> | |
| <span class="stat-card-value" id="stat-benchmarks" data-target="0">0</span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon stat-card-icon--pass"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg> | |
| </div> | |
| <div class="stat-card-content"> | |
| <span class="stat-card-label">Pass Rate</span> | |
| <span class="stat-card-value"><span id="stat-pass-rate" data-target="0">0</span><span class="stat-card-unit">%</span></span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon stat-card-icon--decode"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 17 9 11 13 15 21 7"/><polyline points="14 7 21 7 21 14"/></svg> | |
| </div> | |
| <div class="stat-card-content"> | |
| <span class="stat-card-label">Best Decode</span> | |
| <span class="stat-card-value"><span id="stat-best-decode" data-target="0">0.0</span><span class="stat-card-unit">tok/s</span></span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon stat-card-icon--size"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg> | |
| </div> | |
| <div class="stat-card-content"> | |
| <span class="stat-card-label">Largest Run</span> | |
| <span class="stat-card-value"><span id="stat-largest" data-target="0">0</span><span class="stat-card-unit">MB</span></span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Results --> | |
| <section id="results-section" class="dash-section"> | |
| <div class="container"> | |
| <div class="section-header"> | |
| <h2>Results</h2> | |
| <span class="results-count" id="results-count"></span> | |
| </div> | |
| <div class="table-card"> | |
| <div class="results-wrapper" id="results-table" tabindex="0" role="region" aria-label="Benchmark results table"></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Performance Charts --> | |
| <section id="performance-section" class="dash-section"> | |
| <div class="container"> | |
| <div class="section-header"> | |
| <h2>Performance</h2> | |
| </div> | |
| <div class="charts-grid"> | |
| <div class="chart-box"><canvas id="chart-decode"></canvas></div> | |
| <div class="chart-box"><canvas id="chart-prefill"></canvas></div> | |
| <div class="chart-box"><canvas id="chart-size"></canvas></div> | |
| <div class="chart-box" id="machine-chart-section"><canvas id="chart-machine"></canvas></div> | |
| </div> | |
| <div class="section-header" style="margin-top: 32px;"> | |
| <h3 class="subsection-title">CPU vs WebGPU</h3> | |
| <div class="metric-selector"> | |
| <label class="metric-selector-label" for="cpu-gpu-metric">Metric</label> | |
| <select id="cpu-gpu-metric" class="filter-select" aria-label="CPU vs WebGPU metric"> | |
| <option value="decode_tok_s">Decode tok/s</option> | |
| <option value="prefill_tok_s">Prefill tok/s</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="charts-grid"> | |
| <div class="chart-box"><canvas id="chart-cpu-gpu"></canvas></div> | |
| <div class="chart-box"><canvas id="chart-speedup"></canvas></div> | |
| </div> | |
| <div id="cpu-gpu-table" style="margin-top: 16px;"></div> | |
| </div> | |
| </section> | |
| <!-- Error Analysis --> | |
| <section id="errors-section" class="dash-section"> | |
| <div class="container"> | |
| <div class="section-header"> | |
| <h2>Error Analysis</h2> | |
| </div> | |
| <div id="error-table"></div> | |
| </div> | |
| </section> | |
| <!-- Machines --> | |
| <section id="machines-section" class="dash-section"> | |
| <div class="container"> | |
| <div class="section-header"> | |
| <h2>Machines</h2> | |
| </div> | |
| <div id="machine-info"></div> | |
| </div> | |
| </section> | |
| </div> | |
| </main> | |
| <script type="module" src="js/app.js"></script> | |
| </body> | |
| </html> | |