This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging
The last article introduced the open source packaging tool ESBuild, the basic introduction and packaging speed comparison, and some of the principles of knowledge. This article continues to introduce the principles of ESbuild knowledge, content from esbuild website, plus their own understanding and analysis, there are described incorrect place, welcome to discuss guidance ~
So, let’s review the four aspects of esBuild internal packaging speed optimization described in the previous article:
-
- Esbuild is written in the Go language and compiled to Native code
-
- Extensive use of parallelism and full use of multi-core cpus
-
- Everything in esBuild is written from scratch and no third-party libraries are used
-
- Memory is used efficiently
Here we will introduce each of them:
1. Esbuild is written in Go and compiled to Native code
Most other packagers, because they are written in JavaScript, are slower because each compilation starts with parsing the packager’s code before actually compiling the JavaScript code. Go, which is not a dynamically compiled language, eliminates this step.
Also, parallelism is at the heart of Go; JavaScript is not. Go can share memory directly across threads, and JavaScript needs to serialize data between threads. Both Go and JavaScript have parallel garbage collectors, but Go’s heap is shared across all threads and JavaScript has a separate heap per thread. Based on tests, this seems to cut JavaScript parallelism in half, probably because the CPU’s core, one half, is busy garbage collecting for the other half.
2. Use parallelism heavily
Esbuild uses an internal algorithm to make full use of the multi-core CPU. The compilation process has three stages: Parsing, linking, and code Generation. Parsing and code generation do most of the work, and can be done completely in parallel (for the most part, linking is a serial task).
As mentioned above, all threads can share memory. Tasks can be easily shared when the same JavaScript library is packaged from different entry points. Most computers have multiple cores, so parallelism can be a huge advantage.
3. Everything in esbuild is written from scratch
Esbuild uses no third-party libraries and is written from scratch, which makes the architecture more extensible and has performance advantages
For example, many packaging tools use the Typescript official compiler as a parser, but the Typescript official parser does not make performance a primary concern.
Their code makes heavy use of Megamorphic Object Shapes and unnecessary Dynamic Property accesses(both of which can slow down JavaScript)
And it appears that Typescript parsers still perform type checking when type checking is disabled.
Esbuild customizes Typescript parsers
4. Memory is used efficiently
Ideally, the compiler’s complexity is O(n), so if you’re dealing with large amounts of data, memory access speed can seriously affect performance. The fewer times you modify the data, the faster the compiler will run.
For example, esBuild only involves the entire JavaScript AST three times
-
- Used for lexical analysis, parsing, scoping, and symbol declaration
-
- Binding notation, minimization syntax, compiling JSX/TS to JS, compiling ES-Next to ES-2015
-
- Minimize identifiers, minimize whitespace, generate code, and source map
The AST can be reused to the maximum extent possible, and other packers do these steps separately, not interleaved
If you are not familiar with the principles of esbuild, please comment on them
Esbuild.github. IO/FAQ /#why-is…