Skip to main content

javascript-high-performance

Specialist in JavaScript Performance based on Hands-On JavaScript High Performance (Justin Scherer). Covers profiling and observability with DevTools tools (Chrome Performance/Memory/Rendering tabs, jsPerf, and correct benchmarking), immutability versus mutability trade-offs (Redux, Immutable.js, RAII, lazy evaluation, tail-call, and currying), modern vanilla JavaScript (Collections, Proxies, Typed Arrays, DOM APIs, Fetch/Promises), Svelte as a framework compiled to vanilla, Node.js without a DOM (fs, net, http, streams, and non-blocking I/O), message passing (pipes, sockets, TCP/UDP, HTTP/2, QUIC), data formats alternative to JSON (MessagePack, schema-based Protocol Buffers), Web Workers (dedicated/shared, transferrables, SharedArrayBuffer), Service Workers (offline cache), build and deploy with Rollup/CircleCI, and WebAssembly in the browser.

Datos de origen

Repositorio
dandgabr/Coacus
Última actividad en el origen
28 de septiembre de 2026 a las 14:03
Idioma detectado de SKILL.md
inglés
Estrellas
4
Forks
3

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
7 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
javascript-high-performance
description
Specialist in JavaScript Performance based on Hands-On JavaScript High Performance (Justin Scherer). Covers profiling and observability with DevTools tools (Chrome Performance/Memory/Rendering tabs, jsPerf, and correct benchmarking), immutability versus mutability trade-offs (Redux, Immutable.js, RAII, lazy evaluation, tail-call, and currying), modern vanilla JavaScript (Collections, Proxies, Typed Arrays, DOM APIs, Fetch/Promises), Svelte as a framework compiled to vanilla, Node.js without a DOM (fs, net, http, streams, and non-blocking I/O), message passing (pipes, sockets, TCP/UDP, HTTP/2, QUIC), data formats alternative to JSON (MessagePack, schema-based Protocol Buffers), Web Workers (dedicated/shared, transferrables, SharedArrayBuffer), Service Workers (offline cache), build and deploy with Rollup/CircleCI, and WebAssembly in the browser.
# AI Skill: JavaScript High Performance This skill guides the AI to act as a specialist in **JavaScript performance**, covering everything from profiling with browser tools to code architecture (mutability, streams, workers, data formats, and WASM), based on *Hands-On JavaScript High Performance* (Justin Scherer, Packt). > 📖 **Canonical reference**: see [references/js-high-performance-book-guide.md](references/js-high-performance-book-guide.md) for the chapter-by-chapter summary of the book and [examples/performance-patterns.md](examples/performance-patterns.md) for the practical patterns. --- ## 🧭 General Guideline - **Measure before optimizing**: use the Performance tab of Chrome DevTools to locate the real bottleneck (scripting, rendering, painting) — never optimize based on assumptions. - **Everything is a trade-off**: immutability buys safety at the cost of speed/memory; native collections beat libraries; MessagePack may be neither smaller nor faster than native JSON. Make a conscious choice, not dogma. - **Prefer the runtime's primitives**: the engine (V8 etc.) optimizes built-ins better than libraries; avoid abstraction layers on hot paths. - **Keep the main thread free**: any processing > ~16 ms should be offloaded to Workers, streams, or WASM. --- ## 🔍 1. Profiling and Observability ### Chrome DevTools Tabs - **Performance**: runtime timeline recording (Scripting/Rendering/Painting, call stack flame chart, event log). Use it to find long-running functions, forced reflows, and GC pauses. - **Memory**: heap snapshots (comparison between snapshots to detect memory leaks — objects retained between captures), allocation instrumentation, and allocation timeline. - **Rendering**: FPS meter and paint flashing to detect excessive layouts/paints in real time. - Other engines: Safari (Web Inspector with Timeline), Firefox (Performance tools), and Edge (a Chromium fork) — different engines optimize differently, so validate across multiple browsers. ### Correct Benchmarking (jsPerf and the like) - Beware of **engine optimizations** that distort results (dead code elimination) — consume the results of the test functions. - Compare across **multiple browsers/engines**; no single-engine result is definitive. - Remove stray code from the test cases — any extra work skews the measurements. --- ## ⚖️ 2. Immutability versus Mutability - **Immutability** (Redux, Immutable.js) brings predictability, undo/redo, and cheap change detection (same reference = same data), but in high-performance applications you pay for it with increased time and memory: every change copies structures. - **Immutable.js** (List, Map, Set with structural tries) yields cleaner code and a functional architecture, but for large datasets native operations (`for` loops, arrays, mutable objects) are faster and less memory hungry. - **Hybrid strategy**: immutability in the state/UI layer (a reference change triggers re-render), disciplined mutability on computational hot paths (parsers, data transformations, in-memory joins). - **Safe mutable writing**: encapsulate mutation in small modules (the RAII / scope-bound resource management pattern — release/close resources in the same scope that created them, inspired by C++/Rust); avoid mutating objects shared across modules. ### Functional Techniques with a Conscious Cost - **Lazy evaluation**: generate collections on demand (generators/iterators) instead of materializing giant arrays. - **Tail recursion**: prefer turning recursion into iteration (loops) — engines do not guarantee TCO, and stack overflow is a real risk. - **Currying**: powerful for composition, but it creates closures and intermediate functions — avoid it in extremely high-frequency code. --- ## 🌐 2. Modern Vanilla JavaScript - **Block-scoped let/const**, arrow functions, and modules — modern code is also code the engine optimizes predictably. - **Collections**: `Map`/`Set`/`WeakMap`/`WeakSet` — `WeakMap`/`WeakSet` allow key GC (metadata without leaks); `Map` beats objects as a dictionary for dynamic keys. - **Typed Arrays** (`Int32Array`, `Float64Array`, `ArrayBuffer`): contiguous, typed memory, essential for large numeric data, binary data, and transfer with Workers. - **Proxies and getters/setters**: enable reactivity (the basis of frameworks such as Svelte/Vue), but every access intercepts — do not use them in hot loops. - **Efficient DOM**: centralized `querySelector`/`querySelectorAll`; **Document Fragments** for batch insertions (a single reflow); Shadow DOM and Web Components for encapsulation; `<template>` for cheap markup cloning. - **Fetch + Promises**: Promises are lazy-friendly; `AbortController` support to cancel requests (avoids unnecessary network and parsing work). --- ## 🧩 3. Svelte and the "Compiled to Vanilla" Paradigm - Svelte compiles components into imperative vanilla JS — no virtual DOM, no runtime in production; each state mutation generates minimal, precise DOM update code. - The performance lesson: **less runtime = more speed**. When a framework library is the bottleneck, consider alternatives that push work to build time (compilers, aggressive tree shaking). - Practical applications (Todo, weather app) show that small components with local state avoid cascading re-renders. --- ## 🟩 4. Node.js without a DOM - `package.json` as the configuration hub (scripts, dependencies, type module). - **Native modules**: `fs` (file I/O), `net` (TCP sockets), `http` (server/services) — no libraries for the basics; the standard lib is the fastest. - **Streams and non-blocking I/O**: never read large files entirely into memory — a pipeline with Readable/Writable/Duplex/Transform streams processes in chunks, keeping memory constant and the event loop free. - **Custom streams**: implement `Readable`/`Writable`/`Transform` (with `highWaterMark` for backpressure) and use generators to simplify pipelines. --- ## 📬 5. Message Passing and Protocols (Node.js) - Local/process communication: `net` with Unix domain sockets / TCP, IPC between processes (cluster). - `cluster` module: multiply processes per CPU core to saturate the hardware (Node is single-threaded per process). - **TCP/UDP**: TCP for ordering and reliability; UDP for minimal latency without a handshake. - **HTTP/2**: stream multiplexing on one connection (eliminates HTTP/1.1 head-of-line blocking), header compression. - **HTTP/3/QUIC**: UDP-based, 0-RTT handshake, no TCP head-of-line blocking — the future direction of web transport. --- ## 📦 6. Data Formats - **JSON**: ubiquitous, but verbose and with encode/decode cost on large payloads. - **Schema-less formats**: JSON, XML — self-describing, larger on the wire. - **MessagePack** (e.g., the `what-the-pack` lib): compact binary with buffer pre-allocation; it may be neither smaller nor faster than native `JSON.parse`/`stringify` — always measure. - **Protocol Buffers (proto3)**: a schema shared up front, very compact and fast encoding — the standard for enterprise systems; numeric field IDs make encoding and indexing cheap. - **Custom format**: for extreme cases, a custom binary encoder/decoder (e.g., schema in front of the data) gives the maximum control over size and speed. --- ## 👷 7. Web Workers and Browser Parallelism - **Dedicated Workers**: move heavy work (parsing, transformation, data joins, computation) off the main thread; communicate via `postMessage`. - **Structured clone has a real cost**: sending thousands of objects serializes/deserializes everything — the book's example: 100,000 objects took from 800 ms to 1.7 s and 80–100 MB of heap. Use `Date.now()` + Profiler to visualize the cost. - **Transferrables**: send the `ArrayBuffer` (`postMessage(view, [view.buffer])`) — **zero copy**; the sender loses access, the receiver gains it. For large binary data this is orders of magnitude faster. - **Shared Workers**: one worker shared across multiple pages/tabs (e.g., a shared in-memory cache, a single connection). - **SharedArrayBuffer + Atomics**: true shared memory with synchronization; requires correct COOP/COEP. --- ## 🔁 8. Service Workers and Caching - ServiceWorker lifecycle: install → waiting → activate; intercept requests with the `fetch` event. - **Page/template caching for offline** (Cache Storage API), enabling PWA behavior. - **Save requests for later**: queue offline mutations and replay them when the network returns (a queue pattern in the SW). - A well-done cache is the cheapest optimization: zero network and processing cost on subsequent requests (TTL/LRU to cap growth, as in the static server chapter). --- ## 🏗️ 9. Build, Deploy, and CI/CD - **Rollup**: a bundler optimized for ES modules (ESM) — effective tree shaking, smaller bundles; use it to distribute the application (server + assets) in a single distributable. - Integrate the build into npm scripts (`npm run build`) and the **CircleCI** pipeline (build → tests → security checks → deploy). - Fewer bytes = less main-thread parsing/compiling; tree shaking is a first-order optimization. --- ## ⚙️ 10. WebAssembly in the Browser - For hot paths that even optimized JS cannot satisfy (corrective code generators such as Hamming, heavy parsing, numeric math). - Direct authoring of WAT modules, compiling **C/C++ for the browser**, and shared memory between WASM and JavaScript (Linear Memory over `WebAssembly.Memory`). - A real case from the book: **SQLite compiled to WASM** running in the browser — a complete client-side database. - Sandbox: WASM code does not leak memory across modules; load it via a static server with the MIME type `application/wasm`. --- ## 🧪 Recommended Code Patterns ### Native loop on a hot path (vs. abstraction) ```javascript // ❌ chain of high-order functions on large data: multiple intermediate arrays const positive = data.filter((x) => x > 0).map((x) => x * 2); // ✅ a single loop, no intermediate allocations const result = new Array(data.length); let count = 0; for (let i = 0; i < data.length; i++) { if (data[i] > 0) { result[count++] = data[i] * 2; } } ``` ### Binary Transfer to Workers (zero-copy) ```javascript const view = new Int32Array(1_000_000); // ... populate ... worker.postMessage(view, [view.buffer]); // transfers, does not copy // ⚠️ view is now neutered/detached on the sender ``` ### Fragment for batch DOM insertion ```javascript const frag = document.createDocumentFragment(); for (const item of items) { frag.appendChild(createRow(item)); } container.appendChild(frag); // a single reflow/layout ``` ### Simple LRU/TTL Cache ```javascript const cache = new Map(); const TTL = 5 * 60 * 1000; function getCached(key) { const hit = cache.get(key); if (!hit) return null; if (Date.now() - hit.ts > TTL) { cache.delete(key); // evita crescimento infinito return null; } return hit.value; } ``` --- ## ⚠️ Pitfalls - **Non-deterministic GC**: massive allocation on hot paths (every user event generating objects) causes GC pauses that are hard to predict; reduce the allocation rate, do not trust that "the GC will handle it". - **Layout thrashing / forced synchronous layout**: interleaving reads and writes of layout properties (`offsetHeight` ↔ `style.height`) forces a reflow on every iteration — separate reads from writes (or use requestAnimationFrame batching). - **postMessage with giant objects**: structured clone duplicates memory and freezes the thread — transfer `ArrayBuffer`s or use `SharedArrayBuffer`. - **Misleading benchmarks**: a single engine, eliminated dead code, or stray code skew the results; test across several browsers and make sure to consume the results. - **Runtime dependencies**: immutability/functional helper libraries on large datasets cost more than native — "everything is a trade-off". --- ## 🔗 Integration with Other Skills - [latency-engineering](../../engineering/practices/latency-engineering/SKILL.md): latency laws, tail latency, and elimination of unnecessary work applied to the web. - [code-optimizer](../../roles/code-optimizer/SKILL.md): the algorithm → structure → runtime → parallelism hierarchy applied to JS applications. - [webassembly](../webassembly/SKILL.md): Wasm as the ultimate destination for hot paths (Emscripten, wasm-pack, SharedArrayBuffer/Atomics). - [framework-react](../../frameworks/framework-react/SKILL.md): state immutability, memoization, and re-renders in the React ecosystem. - [framework-vue](../../frameworks/framework-vue/SKILL.md): reactivity based on getters/setters and Proxies (the same fundamentals as the vanilla chapter). - [frontend-developer](../../roles/frontend-developer/SKILL.md): integrating performance optimizations into the UI construction cycle.
Ver en GitHub