Optimizing JavaScript for Fun and for Profit
Optimizing JavaScript code for performance involves benchmarking, avoiding unnecessary work, string comparisons, and diverse object shapes. JavaScript engines optimize based on object shapes, impacting array/object methods and indirection. Creating objects with the same shape improves optimization, cautioning against slower functional programming methods. Costs of indirection like proxy objects and function calls affect performance. Code examples and benchmarks demonstrate optimization variances.
Read original articleThe article discusses optimizing JavaScript code for performance while balancing readability. It emphasizes the importance of benchmarking before optimization and provides tips such as avoiding unnecessary work, string comparisons, and different object shapes to enhance efficiency. It explains how JavaScript engines optimize code based on object shapes and highlights the impact of using array/object methods and indirection on performance. The author suggests creating objects with the same shape to improve optimization and warns against functional programming methods that can be slower than imperative approaches. Additionally, it addresses the costs of indirection, including proxy objects, object access methods, and function calls, on performance. The article includes code examples and benchmarks to illustrate the differences in optimization techniques.
Related
Exposition of Front End Build Systems
Frontend build systems are crucial in web development, involving transpilation, bundling, and minification steps. Tools like Babel and Webpack optimize code for performance and developer experience. Various bundlers like Webpack, Rollup, Parcel, esbuild, and Turbopack are compared for features and performance.
Understanding React Compiler
React's core architecture simplifies app development but can lead to performance issues. The React team introduced React Compiler to automate performance tuning by rewriting code using AST, memoization, and hook storage for optimization.
Optimizing the Roc parser/compiler with data-oriented design
The blog post explores optimizing a parser/compiler with data-oriented design (DoD), comparing Array of Structs and Struct of Arrays for improved performance through memory efficiency and cache utilization. Restructuring data in the Roc compiler showcases enhanced efficiency and performance gains.
Understanding React Compiler
React's core architecture simplifies development but can lead to performance issues. The React team introduced the React Compiler to automate performance tuning by rewriting code. Transpilers like Babel convert JSX for efficiency. Compilers, transpilers, and optimizers analyze and produce equivalent code. React Compiler enhances functionality using Abstract Syntax Trees, memoization, and hook storage for optimized performance.
New Web Development: Or, why Copilots and chatbots are bad for modern web dev
The analysis critiques Copilots, chatbots, and React for web development, citing slow sites, complex code, and high costs. It advocates for a shift to browser APIs, CSS, and HTML for better performance and lower expenses. Transition challenges include finding developers skilled in vanilla JavaScript. Organizations are urged to prioritize simplicity, efficiency, and core web technology training.
This is not true in anything except for toy interpreters, for a number of reasons.
One, internally strings are stored alongside the length. For 'TOP' and 'BOTTOM' the lengths don't match which means the strings can't be equal. That means inequality testing requires only a single integer comparison.
Two, strcmp is used for ordering strings, that's why it returns -1, 0, 1. That additional work isn't needed for testing equality. JS engines are not going to call strcmp unnecessarily.
Three, modern Javascript engines don't treat all strings the same. There are fast paths for ASCII strings, for interned strings, for concatenated strings, for strings that are slices of other strings, and more. From the perspective of the programmer a Javascript string is just a string. In reality a string in Javascript is nothing like C's char*.
I suspect -- but don't actually know -- that the string compare in the benchmark of example 1 is slower because the JS engine has to do a type check on the internal string representation. That's an extra branch the integer path doesn't need.
With that in mind, it’d be interesting to see the relative costs of each deoptimization to the others. For example, is a monomorphic->polymorphic deopt an order of magnitude worse than an unnecessary string mutation? In nanoseconds, what’s the actual cost of each of these? Because there are certainly going to be some optimizations that matter much more than others.
Looking into how to get more debugging information out of a JS engine, I found this V8 blogpost that explains how to install a debugging version of V8 called "D8" [1].
I wish getting debug info was way easier though. Imagine being able to do something like this:
function xyz() { "use debug"; }
--Related
Exposition of Front End Build Systems
Frontend build systems are crucial in web development, involving transpilation, bundling, and minification steps. Tools like Babel and Webpack optimize code for performance and developer experience. Various bundlers like Webpack, Rollup, Parcel, esbuild, and Turbopack are compared for features and performance.
Understanding React Compiler
React's core architecture simplifies app development but can lead to performance issues. The React team introduced React Compiler to automate performance tuning by rewriting code using AST, memoization, and hook storage for optimization.
Optimizing the Roc parser/compiler with data-oriented design
The blog post explores optimizing a parser/compiler with data-oriented design (DoD), comparing Array of Structs and Struct of Arrays for improved performance through memory efficiency and cache utilization. Restructuring data in the Roc compiler showcases enhanced efficiency and performance gains.
Understanding React Compiler
React's core architecture simplifies development but can lead to performance issues. The React team introduced the React Compiler to automate performance tuning by rewriting code. Transpilers like Babel convert JSX for efficiency. Compilers, transpilers, and optimizers analyze and produce equivalent code. React Compiler enhances functionality using Abstract Syntax Trees, memoization, and hook storage for optimized performance.
New Web Development: Or, why Copilots and chatbots are bad for modern web dev
The analysis critiques Copilots, chatbots, and React for web development, citing slow sites, complex code, and high costs. It advocates for a shift to browser APIs, CSS, and HTML for better performance and lower expenses. Transition challenges include finding developers skilled in vanilla JavaScript. Organizations are urged to prioritize simplicity, efficiency, and core web technology training.