Bladeren bron

Optimize performance; remove side effects

Arjun Barrett 4 jaren geleden
bovenliggende
commit
fe2a3b1bcb
7 gewijzigde bestanden met toevoegingen van 40 en 35 verwijderingen
  1. 12 11
      README.md
  2. 7 7
      docs/README.md
  3. 2 2
      docs/interfaces/deflateoptions.md
  4. 4 4
      docs/interfaces/gzipoptions.md
  5. 2 2
      docs/interfaces/zliboptions.md
  6. 6 2
      package.json
  7. 7 7
      src/index.ts

+ 12 - 11
README.md

@@ -2,16 +2,17 @@
 High performance (de)compression in an 8kB package
 
 ## Why fflate?
-`fflate` (short for fast flate) is the **fastest, smallest, and most versatile** pure JavaScript compression and decompression library in existence, handily beating [`pako`](https://npmjs.com/package/pako), [`tiny-inflate`](https://npmjs.com/package/tiny-inflate), and [`UZIP.js`](https://github.com/photopea/UZIP.js) in performance benchmarks while being multiple times more lightweight. It includes support for DEFLATE, GZIP, and Zlib data. Data compressed by `fflate` can be decompressed by other tools, and vice versa.
-
-|                        | `pako` | `tiny-inflate`       | `UZIP.js`         | `fflate`                       |
-|------------------------|--------|----------------------|-------------------|--------------------------------|
-| Relative performance   | 1x     | up to 10x slower     | up to 40% faster  | **Up to 60% faster**           |
-| Bundle size (minified) | 44.5kB | **3 kB**             | 14.2kB            | 8kB **(3kB for only inflate)** |
-| Compression support    | ✅     | ❌                    | ✅                | ✅                             |
-| Thread/Worker safe     | ✅     | ✅                    | ❌                | ✅                             |
-| GZIP/Zlib support      | ✅     | ❌                    | ❌                | ✅                             |
-| Uses ES Modules        | ❌     | ❌                    | ❌                | ✅                             |
+`fflate` (short for fast flate) is the **fastest, smallest, and most versatile** pure JavaScript compression and decompression library in existence, handily beating [`pako`](https://npmjs.com/package/pako), [`tiny-inflate`](https://npmjs.com/package/tiny-inflate), and [`UZIP.js`](https://github.com/photopea/UZIP.js) in performance benchmarks while being multiple times more lightweight. Its compression ratios are often better than even the original Zlib C library. It includes support for DEFLATE, GZIP, and Zlib data. Data compressed by `fflate` can be decompressed by other tools, and vice versa.
+
+|                           | `pako` | `tiny-inflate`       | `UZIP.js`             | `fflate`                       |
+|---------------------------|--------|----------------------|-----------------------|--------------------------------|
+| Decompression performance | 1x     | up to 10x slower     | **up to 40% faster**  | **up to 40% faster**           |
+| Compression performance   | 1x     | N/A                  | up to 5% faster       | **up to 50% faster**           |
+| Bundle size (minified)    | 44.5kB | **3 kB**             | 14.2kB                | 8kB **(3kB for only inflate)** |
+| Compression support       | ✅     | ❌                    | ✅                    | ✅                             |
+| Thread/Worker safe        | ✅     | ✅                    | ❌                    | ✅                             |
+| GZIP/Zlib support         | ✅     | ❌                    | ❌                    | ✅                             |
+| Uses ES Modules           | ❌     | ❌                    | ❌                    | ✅                             |
 
 ## Usage
 
@@ -105,7 +106,7 @@ Note that there exist some small libraries like [`tiny-inflate`](https://npmjs.c
 
 So what makes `fflate` different? It takes the brilliant innovations of `UZIP.js` and optimizes them while adding direct support for GZIP and Zlib data. And unlike all of the above libraries, it uses ES Modules to allow for partial builds, meaning that it can rival even `tiny-inflate` in size while maintaining excellent performance. The end result is a library that, in total, weighs 8kB minified for the entire build (3kB for decompression only and 5kB for compression only), is about 15% faster than `UZIP.js` or up to 60% faster than `pako`, and achieves the same or better compression ratio than the rest.
 
-Before you decide that `fflate` is the end-all compression library, you should note that JavaScript simply cannot rival the performance of a compiled language. If you're willing to have 160 kB of extra weight and [much less browser support](https://caniuse.com/wasm), you can achieve around 30% more performance than `fflate` with a WASM build of Zlib like [`wasm-flate`](https://www.npmjs.com/package/wasm-flate). And if you're only using Node.js, just use the [native Zlib bindings](https://nodejs.org/api/zlib.html) that offer the best performance and compression ratios.
+Before you decide that `fflate` is the end-all compression library, you should note that JavaScript simply cannot rival the performance of a compiled language. If you're willing to have 160 kB of extra weight and [much less browser support](https://caniuse.com/wasm), you can achieve  more performance than `fflate` with a WASM build of Zlib like [`wasm-flate`](https://www.npmjs.com/package/wasm-flate). And if you're only using Node.js, just use the [native Zlib bindings](https://nodejs.org/api/zlib.html) that offer the best performance. Though note that even against these compiled libraries, `fflate` is only around 30% slower in decompression and 10% slower in compression, and can still achieve better compression ratios!
 
 ## Browser support
 `fflate` makes heavy use of typed arrays (`Uint8Array`, `Uint16Array`, etc.). Typed arrays can be polyfilled at the cost of performance, but the most recent browser that doesn't support them [is from 2011](https://caniuse.com/typedarrays), so I wouldn't bother.

+ 7 - 7
docs/README.md

@@ -24,7 +24,7 @@
 
 ▸ **decompress**(`data`: Uint8Array, `out?`: Uint8Array): Uint8Array
 
-*Defined in [index.ts:774](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L774)*
+*Defined in [index.ts:774](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L774)*
 
 Expands compressed GZIP, Zlib, or raw DEFLATE data, automatically detecting the format
 
@@ -43,7 +43,7 @@ ___
 
 ▸ **deflate**(`data`: Uint8Array, `opts`: [DeflateOptions](interfaces/deflateoptions.md)): Uint8Array
 
-*Defined in [index.ts:680](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L680)*
+*Defined in [index.ts:680](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L680)*
 
 Compresses data with DEFLATE without any wrapper
 
@@ -62,7 +62,7 @@ ___
 
 ▸ **gunzip**(`data`: Uint8Array, `out?`: Uint8Array): Uint8Array
 
-*Defined in [index.ts:720](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L720)*
+*Defined in [index.ts:720](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L720)*
 
 Expands GZIP data
 
@@ -81,7 +81,7 @@ ___
 
 ▸ **gzip**(`data`: Uint8Array, `opts`: [GZIPOptions](interfaces/gzipoptions.md)): Uint8Array
 
-*Defined in [index.ts:700](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L700)*
+*Defined in [index.ts:700](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L700)*
 
 Compresses data with GZIP
 
@@ -100,7 +100,7 @@ ___
 
 ▸ **inflate**(`data`: Uint8Array, `out?`: Uint8Array): Uint8Array
 
-*Defined in [index.ts:690](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L690)*
+*Defined in [index.ts:690](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L690)*
 
 Expands DEFLATE data with no wrapper
 
@@ -119,7 +119,7 @@ ___
 
 ▸ **unzlib**(`data`: Uint8Array, `out?`: Uint8Array): Uint8Array
 
-*Defined in [index.ts:758](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L758)*
+*Defined in [index.ts:758](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L758)*
 
 Expands Zlib data
 
@@ -138,7 +138,7 @@ ___
 
 ▸ **zlib**(`data`: Uint8Array, `opts`: [ZlibOptions](interfaces/zliboptions.md)): Uint8Array
 
-*Defined in [index.ts:737](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L737)*
+*Defined in [index.ts:737](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L737)*
 
 Compress data with Zlib
 

+ 2 - 2
docs/interfaces/deflateoptions.md

@@ -23,7 +23,7 @@ Options for compressing data into a DEFLATE format
 
 • `Optional` **level**: 0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9
 
-*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L632)*
+*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L632)*
 
 The level of compression to use, ranging from 0-9.
 
@@ -45,7 +45,7 @@ ___
 
 • `Optional` **mem**: 0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 11 \| 12
 
-*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L641)*
+*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L641)*
 
 The memory level to use, ranging from 0-12. Increasing this increases speed and compression ratio at the cost of memory.
 

+ 4 - 4
docs/interfaces/gzipoptions.md

@@ -23,7 +23,7 @@ Options for compressing data into a GZIP format
 
 • `Optional` **filename**: string
 
-*Defined in [index.ts:657](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L657)*
+*Defined in [index.ts:657](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L657)*
 
 The filename of the data. If the `gunzip` command is used to decompress the data, it will output a file
 with this name instead of the name of the compressed file.
@@ -36,7 +36,7 @@ ___
 
 *Inherited from [DeflateOptions](deflateoptions.md).[level](deflateoptions.md#level)*
 
-*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L632)*
+*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L632)*
 
 The level of compression to use, ranging from 0-9.
 
@@ -60,7 +60,7 @@ ___
 
 *Inherited from [DeflateOptions](deflateoptions.md).[mem](deflateoptions.md#mem)*
 
-*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L641)*
+*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L641)*
 
 The memory level to use, ranging from 0-12. Increasing this increases speed and compression ratio at the cost of memory.
 
@@ -75,7 +75,7 @@ ___
 
 • `Optional` **mtime**: Date \| string \| number
 
-*Defined in [index.ts:652](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L652)*
+*Defined in [index.ts:652](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L652)*
 
 When the file was last modified. Defaults to the current time.
 Set this to 0 to avoid specifying a modification date entirely.

+ 2 - 2
docs/interfaces/zliboptions.md

@@ -23,7 +23,7 @@ Options for compressing data into a Zlib format
 
 *Inherited from [DeflateOptions](deflateoptions.md).[level](deflateoptions.md#level)*
 
-*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L632)*
+*Defined in [index.ts:632](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L632)*
 
 The level of compression to use, ranging from 0-9.
 
@@ -47,7 +47,7 @@ ___
 
 *Inherited from [DeflateOptions](deflateoptions.md).[mem](deflateoptions.md#mem)*
 
-*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/9ef7e32/src/index.ts#L641)*
+*Defined in [index.ts:641](https://github.com/101arrowz/fflate/blob/8a52440/src/index.ts#L641)*
 
 The memory level to use, ranging from 0-12. Increasing this increases speed and compression ratio at the cost of memory.
 

+ 6 - 2
package.json

@@ -1,10 +1,11 @@
 {
   "name": "fflate",
-  "version": "0.0.2",
+  "version": "0.0.3",
   "description": "High performance (de)compression in an 8kB package",
   "main": "lib/index.js",
   "module": "esm/index.js",
   "types": "lib/index.d.ts",
+  "sideEffects": false,
   "repository": "https://github.com/101arrowz/fflate",
   "author": "Arjun Barrett",
   "license": "MIT",
@@ -16,7 +17,10 @@
     "compression",
     "decompression",
     "zlib",
-    "pako"
+    "pako",
+    "browser",
+    "node.js",
+    "tiny"
   ],
   "scripts": {
     "build": "tsc && tsc --project tsconfig.esm.json && typedoc --mode library --plugin typedoc-plugin-markdown --hideProjectName --hideBreadcrumbs --readme none",

+ 7 - 7
src/index.ts

@@ -138,8 +138,8 @@ const bits16 = (d: Uint8Array, p: number) => {
 const inflt = (dat: Uint8Array, buf?: Uint8Array) => {
   // have to estimate size
   const noBuf = !buf;
-  // Slightly less than 2x - assumes ~60% compression ratio
-  if (noBuf) buf = new u8((dat.length >>> 2) << 3);
+  // 4x - assumes ~25% compression ratio
+  if (noBuf) buf = new u8(dat.length << 2);
   // ensure buffer can fit at least l elements
   const cbuf = (l: number) => {
     let bl = buf.length;
@@ -166,13 +166,13 @@ const inflt = (dat: Uint8Array, buf?: Uint8Array) => {
     if (!type) {
       // go to end of byte boundary
       if (pos & 7) pos += 8 - (pos & 7);
-      const s = (pos >>> 3) + 4, l = dat[s - 4] | (dat[s - 3] << 8);
+      let s = (pos >>> 3) + 4, l = dat[s - 4] | (dat[s - 3] << 8);
       // ensure size
       if (noBuf) cbuf(bt + l);
       // Copy over uncompressed data
-      buf.set(dat.subarray(s, s + l), bt);
+      for (let m = s + l; s < m; ++s) buf[bt++] = dat[s];
       // Get new bitpos, update byte count
-      pos = (s + l) << 3, bt += l;
+      pos = s << 3;
       continue;
     }
     // Make sure the buffer can hold this + the largest possible addition
@@ -488,7 +488,7 @@ const wblk = (dat: Uint8Array, out: Uint8Array, final: number, syms: Uint32Array
 }
 
 // deflate options (nice << 13) | chain
-const deo = new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
+const deo = /*#__PURE__*/new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
 
 // compresses data into a raw DEFLATE buffer
 const dflt = (dat: Uint8Array, lvl: number, plvl: number, pre: number, post: number) => {
@@ -724,7 +724,7 @@ export function gunzip(data: Uint8Array, out?: Uint8Array) {
   let st = 10 + (flg & 2);
   if (flg & 4) st += data[10] | (data[11] << 8) + 2;
   for (let zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= (data[st++] == 0) as unknown as number);
-  if (!out) out = new Uint8Array(data[l - 4] | data[l - 3] << 8 | data[l - 2] << 16 | data[l - 1] << 24);
+  if (!out) out = new u8(data[l - 4] | data[l - 3] << 8 | data[l - 2] << 16 | data[l - 1] << 24);
   return inflt(data.subarray(st, -8), out);
 }