Spaces:
Running
Running
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <style> | |
| :root { | |
| --paper: #f2ede3; | |
| --raised: #fbf7f0; | |
| --ink: #1b1714; | |
| --body: #3f382f; | |
| --soft: #756a5e; | |
| --faint: #9a9081; | |
| --orange: #c6531d; | |
| --pine: #2f5a3c; | |
| --hairline: #d7cbb6; | |
| --sunken: #ece5d7; | |
| } | |
| * { box-sizing: border-box; } | |
| body { | |
| margin: 0; | |
| background: var(--paper); | |
| color: var(--ink); | |
| font-family: Arial, Helvetica, sans-serif; | |
| } | |
| .frame { | |
| min-height: 100vh; | |
| padding: 0; | |
| background: var(--paper); | |
| } | |
| .chart { | |
| border: 1px solid var(--ink); | |
| background: var(--raised); | |
| color: var(--ink); | |
| overflow: hidden; | |
| } | |
| .chart-header { | |
| border-bottom: 1px solid var(--hairline); | |
| padding: 18px 20px 16px; | |
| } | |
| .chart-header-row { | |
| align-items: flex-start; | |
| display: flex; | |
| gap: 18px; | |
| justify-content: space-between; | |
| } | |
| h1 { | |
| margin: 0; | |
| font-family: Arial, Helvetica, sans-serif; | |
| font-size: clamp(24px, 4vw, 34px); | |
| line-height: 1.08; | |
| } | |
| .summary { | |
| margin: 8px 0 0; | |
| color: var(--body); | |
| font: 15px/1.45 Georgia, serif; | |
| } | |
| .summary strong { | |
| color: var(--orange); | |
| font-family: ui-monospace, SFMono-Regular, Menlo, monospace; | |
| font-size: 16px; | |
| font-weight: 500; | |
| } | |
| .tabs { | |
| border: 1px solid var(--hairline); | |
| display: inline-flex; | |
| flex: 0 0 auto; | |
| } | |
| .tabs button { | |
| background: transparent; | |
| border: 0; | |
| color: var(--soft); | |
| cursor: pointer; | |
| font: 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| letter-spacing: .10em; | |
| padding: 10px 13px; | |
| } | |
| .tabs button + button { border-left: 1px solid var(--hairline); } | |
| .tabs button[aria-selected="true"] { | |
| background: var(--ink); | |
| color: var(--paper); | |
| } | |
| .scatter-shell { | |
| min-height: 520px; | |
| padding: 28px 28px 58px 68px; | |
| position: relative; | |
| } | |
| .scatter { | |
| border-bottom: 1px solid var(--soft); | |
| border-left: 1px solid var(--soft); | |
| height: 430px; | |
| position: relative; | |
| } | |
| .quality-zone { | |
| background: rgba(47, 90, 60, .055); | |
| border: 1px solid rgba(47, 90, 60, .08); | |
| bottom: 0; | |
| pointer-events: none; | |
| position: absolute; | |
| right: 0; | |
| top: 0; | |
| width: 24%; | |
| } | |
| .grid-x, | |
| .grid-y { | |
| color: var(--faint); | |
| font: 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| position: absolute; | |
| } | |
| .grid-x { | |
| border-left: 1px solid rgba(27, 23, 20, .12); | |
| bottom: 0; | |
| top: 0; | |
| } | |
| .grid-x span { | |
| position: absolute; | |
| top: calc(100% + 13px); | |
| transform: translateX(-50%); | |
| white-space: nowrap; | |
| } | |
| .grid-y { | |
| border-top: 1px solid rgba(27, 23, 20, .12); | |
| left: 0; | |
| right: 0; | |
| } | |
| .grid-y span { | |
| position: absolute; | |
| right: calc(100% + 12px); | |
| transform: translateY(-50%); | |
| } | |
| .axis-x, | |
| .axis-y { | |
| color: var(--soft); | |
| font: 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| letter-spacing: .08em; | |
| position: absolute; | |
| text-transform: uppercase; | |
| } | |
| .axis-x { | |
| bottom: 18px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| } | |
| .axis-y { | |
| left: 17px; | |
| top: 46%; | |
| transform: translateY(-50%) rotate(180deg); | |
| writing-mode: vertical-rl; | |
| } | |
| .guide { | |
| border-top: 2px dashed rgba(198, 83, 29, .48); | |
| pointer-events: none; | |
| position: absolute; | |
| } | |
| .callout { | |
| background: rgba(251, 247, 240, .94); | |
| border: 1px solid var(--hairline); | |
| color: var(--orange); | |
| font: 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| letter-spacing: .04em; | |
| padding: 8px 10px; | |
| position: absolute; | |
| white-space: nowrap; | |
| z-index: 4; | |
| } | |
| button.point { | |
| align-items: center; | |
| background: transparent; | |
| border: 0; | |
| cursor: pointer; | |
| display: flex; | |
| height: 36px; | |
| justify-content: center; | |
| padding: 0; | |
| position: absolute; | |
| transform: translate(-50%, -50%); | |
| width: 36px; | |
| z-index: 3; | |
| } | |
| .marker { | |
| --size: 14px; | |
| display: block; | |
| height: var(--size); | |
| position: relative; | |
| transition: transform 120ms ease, opacity 120ms ease; | |
| width: var(--size); | |
| } | |
| [aria-pressed="true"] > .marker, | |
| .point[aria-pressed="true"] .marker { | |
| transform: scale(1.32); | |
| } | |
| .marker-circle, | |
| .marker-square, | |
| .marker-diamond { | |
| background: var(--c); | |
| border: 1px solid var(--raised); | |
| } | |
| .marker-circle { border-radius: 999px; } | |
| .marker-diamond { transform: rotate(45deg); } | |
| [aria-pressed="true"] > .marker-diamond, | |
| .point[aria-pressed="true"] .marker-diamond { | |
| transform: rotate(45deg) scale(1.32); | |
| } | |
| .marker-triangle { | |
| height: 0; | |
| width: 0; | |
| border-bottom: 16px solid var(--c); | |
| border-left: 9px solid transparent; | |
| border-right: 9px solid transparent; | |
| } | |
| .marker-plus::before, | |
| .marker-plus::after, | |
| .marker-x::before, | |
| .marker-x::after { | |
| background: var(--c); | |
| content: ""; | |
| left: 50%; | |
| position: absolute; | |
| top: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| .marker-plus::before, | |
| .marker-x::before { | |
| height: 18px; | |
| width: 2px; | |
| } | |
| .marker-plus::after, | |
| .marker-x::after { | |
| height: 2px; | |
| width: 18px; | |
| } | |
| .marker-x { transform: rotate(45deg); } | |
| [aria-pressed="true"] > .marker-x, | |
| .point[aria-pressed="true"] .marker-x { | |
| transform: rotate(45deg) scale(1.32); | |
| } | |
| .inline-label { | |
| background: rgba(251, 247, 240, .86); | |
| color: var(--soft); | |
| font: 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| padding: 3px 5px; | |
| pointer-events: none; | |
| position: absolute; | |
| transform: translateX(10px); | |
| white-space: nowrap; | |
| z-index: 2; | |
| } | |
| .inline-label-small { | |
| color: var(--orange); | |
| transform: translateX(calc(-100% - 10px)); | |
| } | |
| .tooltip { | |
| background: var(--ink); | |
| border: 1px solid var(--ink); | |
| color: var(--paper); | |
| display: grid; | |
| gap: 4px; | |
| font: 11px/1.25 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| left: 0; | |
| min-width: 132px; | |
| padding: 8px 10px; | |
| pointer-events: none; | |
| position: absolute; | |
| top: 0; | |
| transform: translate(-50%, calc(-100% - 18px)); | |
| z-index: 5; | |
| } | |
| .tooltip strong { | |
| color: var(--paper); | |
| font: 13px/1.2 Georgia, serif; | |
| } | |
| .tooltip span { color: rgba(242, 237, 227, .7); } | |
| .tooltip b { | |
| color: var(--paper); | |
| font-weight: 500; | |
| } | |
| .tooltip[hidden] { display: none; } | |
| .chart-footer { | |
| align-items: center; | |
| border-top: 1px solid var(--hairline); | |
| display: flex; | |
| gap: 20px; | |
| justify-content: space-between; | |
| padding: 16px 20px; | |
| } | |
| .legend { | |
| display: flex; | |
| flex: 1 1 auto; | |
| flex-wrap: wrap; | |
| gap: 10px 16px; | |
| min-width: 0; | |
| } | |
| .legend button { | |
| align-items: center; | |
| background: transparent; | |
| border: 0; | |
| color: var(--body); | |
| cursor: pointer; | |
| display: inline-flex; | |
| font: 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| gap: 8px; | |
| padding: 0; | |
| } | |
| .legend button[aria-pressed="false"] { opacity: .62; } | |
| .readouts { | |
| display: flex; | |
| flex: 0 0 auto; | |
| flex-wrap: nowrap; | |
| gap: 14px; | |
| justify-content: flex-end; | |
| } | |
| .readouts div { | |
| border-left: 1px solid var(--hairline); | |
| min-width: 96px; | |
| padding-left: 12px; | |
| } | |
| .readouts span { | |
| color: var(--faint); | |
| display: block; | |
| font: 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| letter-spacing: .12em; | |
| text-transform: uppercase; | |
| } | |
| .readouts strong { | |
| color: var(--ink); | |
| display: block; | |
| font: 500 15px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| margin-top: 5px; | |
| } | |
| .readouts em { | |
| color: var(--soft); | |
| display: block; | |
| font: 12px/1.2 Georgia, serif; | |
| font-style: normal; | |
| margin-top: 5px; | |
| max-width: 126px; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .bar-panel { | |
| padding: 20px; | |
| } | |
| .bar-meta { | |
| color: var(--soft); | |
| display: flex; | |
| font: 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| justify-content: space-between; | |
| letter-spacing: .08em; | |
| margin-bottom: 16px; | |
| text-transform: uppercase; | |
| } | |
| .bars { | |
| display: grid; | |
| gap: 12px; | |
| } | |
| .row { | |
| background: var(--paper); | |
| border: 1px solid var(--hairline); | |
| color: var(--ink); | |
| cursor: pointer; | |
| padding: 14px; | |
| text-align: left; | |
| width: 100%; | |
| } | |
| .row[aria-pressed="true"] { | |
| border-color: var(--ink); | |
| } | |
| .row-top { | |
| align-items: baseline; | |
| display: flex; | |
| font: 13px/1 ui-monospace, SFMono-Regular, Menlo, monospace; | |
| gap: 16px; | |
| justify-content: space-between; | |
| } | |
| .row-top strong { | |
| font-weight: 500; | |
| } | |
| .track { | |
| background: var(--sunken); | |
| display: block; | |
| height: 12px; | |
| margin-top: 12px; | |
| } | |
| .fill { | |
| background: var(--c); | |
| display: block; | |
| height: 100%; | |
| min-width: 5%; | |
| transition: width 160ms ease; | |
| width: var(--w); | |
| } | |
| .bar-footer { | |
| justify-content: flex-end; | |
| } | |
| @media (max-width: 640px) { | |
| .chart-header-row, | |
| .chart-footer { | |
| align-items: stretch; | |
| flex-direction: column; | |
| } | |
| .scatter-shell { | |
| min-height: 470px; | |
| padding: 24px 18px 58px 44px; | |
| } | |
| .scatter { height: 370px; } | |
| .inline-label { display: none; } | |
| .legend { | |
| flex: 0 1 auto; | |
| gap: 8px 14px; | |
| } | |
| .readouts { justify-content: flex-start; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <main class="frame"> | |
| <section class="chart" data-space-chart="throughput"> | |
| <header class="chart-header chart-header-row"> | |
| <div> | |
| <h1>Throughput by Model</h1> | |
| <p class="summary"><strong data-bar-ratio>20x</strong> faster than Dripper on <span data-bar-hardware>L4</span>, comparing Pulpie Small on the same pages.</p> | |
| </div> | |
| <div class="tabs" role="tablist" aria-label="Hardware"><button type="button" role="tab" data-hardware-tab="l4" data-ratio="20x" data-hardware-label="L4" aria-selected="true">L4</button><button type="button" role="tab" data-hardware-tab="a100" data-ratio="7.1x" data-hardware-label="A100" aria-selected="false">A100</button></div> | |
| </header> | |
| <div class="bar-panel" data-hardware-panel="l4" ><div class="bar-meta"><span>NVIDIA L4</span><span>Pages/sec</span></div><div class="bars"><button type="button" class="row" data-model-id="pulpie-small" data-label="Pulpie Small" data-primary="13.7 p/s" data-secondary="$7.9K" aria-pressed="true" style="--w:100.000%;--c:#c6531d"><span class="row-top"><span>Pulpie Small</span><strong>13.7 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="pulpie-base" data-label="Pulpie Base" data-primary="3.9 p/s" data-secondary="$28K" aria-pressed="false" style="--w:28.467%;--c:#2f5a3c"><span class="row-top"><span>Pulpie Base</span><strong>3.9 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="pulpie-large" data-label="Pulpie Large" data-primary="1.3 p/s" data-secondary="$83K" aria-pressed="false" style="--w:9.489%;--c:#756a5e"><span class="row-top"><span>Pulpie Large</span><strong>1.3 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="dripper" data-label="Dripper" data-primary="0.68 p/s" data-secondary="$159K" aria-pressed="false" style="--w:5.000%;--c:#1b1714"><span class="row-top"><span>Dripper</span><strong>0.68 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button></div><footer class="chart-footer bar-footer"><div class="readouts"><div><span>Selected</span><strong data-selected-primary>13.7 p/s</strong><em data-selected-label>Pulpie Small</em></div><div><span>Cost</span><strong data-selected-secondary>$7.9K</strong><em>per 1B pages</em></div></div></footer></div><div class="bar-panel" data-hardware-panel="a100" hidden><div class="bar-meta"><span>NVIDIA A100</span><span>Pages/sec</span></div><div class="bars"><button type="button" class="row" data-model-id="pulpie-small" data-label="Pulpie Small" data-primary="25.7 p/s" data-secondary="$29K" aria-pressed="true" style="--w:100.000%;--c:#c6531d"><span class="row-top"><span>Pulpie Small</span><strong>25.7 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="pulpie-base" data-label="Pulpie Base" data-primary="7.7 p/s" data-secondary="$98K" aria-pressed="false" style="--w:29.961%;--c:#2f5a3c"><span class="row-top"><span>Pulpie Base</span><strong>7.7 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="pulpie-large" data-label="Pulpie Large" data-primary="3.5 p/s" data-secondary="$216K" aria-pressed="false" style="--w:13.619%;--c:#756a5e"><span class="row-top"><span>Pulpie Large</span><strong>3.5 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button><button type="button" class="row" data-model-id="dripper" data-label="Dripper" data-primary="3.6 p/s" data-secondary="$210K" aria-pressed="false" style="--w:14.008%;--c:#1b1714"><span class="row-top"><span>Dripper</span><strong>3.6 p/s</strong></span><span class="track" aria-hidden="true"><span class="fill"></span></span></button></div><footer class="chart-footer bar-footer"><div class="readouts"><div><span>Selected</span><strong data-selected-primary>25.7 p/s</strong><em data-selected-label>Pulpie Small</em></div><div><span>Cost</span><strong data-selected-secondary>$29K</strong><em>per 1B pages</em></div></div></footer></div> | |
| </section> | |
| </main> | |
| <script> | |
| document.querySelectorAll("[data-space-chart]").forEach((chart) => { | |
| const pointSources = new Map( | |
| Array.from(chart.querySelectorAll("[data-point-source]")).map((item) => [ | |
| item.dataset.pointId, | |
| item, | |
| ]), | |
| ); | |
| const tooltip = chart.querySelector("[data-quality-tooltip]"); | |
| function setPoint(id) { | |
| const selected = pointSources.get(id); | |
| if (!selected) return; | |
| chart.querySelectorAll("[data-point-id]").forEach((item) => { | |
| item.setAttribute("aria-pressed", String(item.dataset.pointId === id)); | |
| }); | |
| const label = selected.dataset.label || ""; | |
| const quality = selected.dataset.quality || ""; | |
| const cost = selected.dataset.cost || ""; | |
| const selectedLabel = chart.querySelector("[data-selected-label]"); | |
| const selectedQuality = chart.querySelector("[data-selected-quality]"); | |
| const selectedCost = chart.querySelector("[data-selected-cost]"); | |
| if (selectedLabel) selectedLabel.textContent = label; | |
| if (selectedQuality) selectedQuality.textContent = quality; | |
| if (selectedCost) selectedCost.textContent = cost; | |
| if (tooltip) { | |
| tooltip.hidden = false; | |
| tooltip.style.left = `${selected.dataset.left || 50}%`; | |
| tooltip.style.top = `${selected.dataset.top || 50}%`; | |
| const tooltipLabel = tooltip.querySelector("[data-tooltip-label]"); | |
| const tooltipQuality = tooltip.querySelector("[data-tooltip-quality]"); | |
| const tooltipCost = tooltip.querySelector("[data-tooltip-cost]"); | |
| if (tooltipLabel) tooltipLabel.textContent = label; | |
| if (tooltipQuality) tooltipQuality.textContent = quality; | |
| if (tooltipCost) tooltipCost.textContent = cost; | |
| } | |
| } | |
| chart.querySelectorAll("[data-point-id]").forEach((item) => { | |
| const activate = () => setPoint(item.dataset.pointId); | |
| item.addEventListener("click", activate); | |
| item.addEventListener("focus", activate); | |
| item.addEventListener("mouseenter", activate); | |
| item.addEventListener("pointerenter", activate); | |
| }); | |
| chart.querySelector(".scatter")?.addEventListener("mouseleave", () => { | |
| if (tooltip) tooltip.hidden = true; | |
| }); | |
| function setHardware(id) { | |
| const tab = chart.querySelector(`[data-hardware-tab="${id}"]`); | |
| chart.querySelectorAll("[data-hardware-tab]").forEach((item) => { | |
| item.setAttribute("aria-selected", String(item.dataset.hardwareTab === id)); | |
| }); | |
| chart.querySelectorAll("[data-hardware-panel]").forEach((panel) => { | |
| panel.hidden = panel.dataset.hardwarePanel !== id; | |
| }); | |
| const ratio = chart.querySelector("[data-bar-ratio]"); | |
| const hardware = chart.querySelector("[data-bar-hardware]"); | |
| if (ratio && tab?.dataset.ratio) ratio.textContent = tab.dataset.ratio; | |
| if (hardware && tab?.dataset.hardwareLabel) hardware.textContent = tab.dataset.hardwareLabel; | |
| } | |
| chart.querySelectorAll("[data-hardware-tab]").forEach((tab) => { | |
| tab.addEventListener("click", () => setHardware(tab.dataset.hardwareTab)); | |
| }); | |
| chart.querySelectorAll("[data-hardware-panel]").forEach((panel) => { | |
| function setModel(id) { | |
| const row = panel.querySelector(`[data-model-id="${id}"]`); | |
| if (!row) return; | |
| panel.querySelectorAll("[data-model-id]").forEach((item) => { | |
| item.setAttribute("aria-pressed", String(item.dataset.modelId === id)); | |
| }); | |
| const selectedLabel = panel.querySelector("[data-selected-label]"); | |
| const selectedPrimary = panel.querySelector("[data-selected-primary]"); | |
| const selectedSecondary = panel.querySelector("[data-selected-secondary]"); | |
| if (selectedLabel) selectedLabel.textContent = row.dataset.label || ""; | |
| if (selectedPrimary) selectedPrimary.textContent = row.dataset.primary || ""; | |
| if (selectedSecondary) selectedSecondary.textContent = row.dataset.secondary || ""; | |
| } | |
| panel.querySelectorAll("[data-model-id]").forEach((row) => { | |
| const activate = () => setModel(row.dataset.modelId); | |
| row.addEventListener("click", activate); | |
| row.addEventListener("focus", activate); | |
| row.addEventListener("mouseenter", activate); | |
| row.addEventListener("pointerenter", activate); | |
| }); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |