|
2 | 2 | /** biome-ignore-all lint/suspicious/noConsole: benckmark */ |
3 | 3 |
|
4 | 4 | import * as scure from '@scure/base' |
5 | | -import bench from 'micro-bmark' |
| 5 | +import { Bench } from 'tinybench' |
| 6 | +import * as rfc4648 from './src/bases/rfc4648.js' |
6 | 7 | import * as iso from './src/index.js' |
7 | 8 |
|
| 9 | +/** |
| 10 | + * Codecs to benchmark |
| 11 | + * @type {Record<string, { |
| 12 | + * encode: Record<string, (buf: Uint8Array) => string>, |
| 13 | + * decode: Record<string, (str: string) => Uint8Array>, |
| 14 | + * }>} |
| 15 | + */ |
8 | 16 | const codecs = { |
9 | 17 | Hex: { |
10 | 18 | encode: { |
11 | 19 | node: (buf) => Buffer.from(buf).toString('hex'), |
12 | | - iso: (buf) => iso.hex.encode(buf), |
| 20 | + iso: (buf) => iso.Rfc4648.hex.encode(buf), |
13 | 21 | scure: (buf) => scure.hex.encode(buf), |
| 22 | + web: (buf) => buf.toHex(), |
14 | 23 | }, |
15 | 24 | decode: { |
16 | 25 | node: (str) => Buffer.from(str, 'hex'), |
17 | | - iso: (str) => iso.hex.decode(str), |
| 26 | + iso: (str) => iso.Rfc4648.hex.decode(str), |
18 | 27 | scure: (str) => scure.hex.decode(str), |
| 28 | + web: (str) => Uint8Array.fromHex(str), |
| 29 | + isoNew: (str) => rfc4648.hex.decode(str), |
19 | 30 | }, |
20 | 31 | }, |
21 | | - Base64: { |
22 | | - encode: { |
23 | | - node: (buf) => Buffer.from(buf).toString('base64'), |
24 | | - iso: (buf) => iso.base64.encode(buf), |
25 | | - scure: (buf) => scure.base64.encode(buf), |
26 | | - }, |
27 | | - decode: { |
28 | | - node: (str) => Buffer.from(str, 'base64'), |
29 | | - iso: (str) => iso.base64.decode(str), |
30 | | - noble: (str) => scure.base64.decode(str), |
31 | | - }, |
32 | | - }, |
| 32 | + // Base64: { |
| 33 | + // encode: { |
| 34 | + // node: (buf) => Buffer.from(buf).toString('base64'), |
| 35 | + // iso: (buf) => iso.Rfc4648.base64.encode(buf), |
| 36 | + // scure: (buf) => scure.base64.encode(buf), |
| 37 | + // web: (buf) => buf.toBase64(), |
| 38 | + // }, |
| 39 | + // decode: { |
| 40 | + // node: (str) => Buffer.from(str, 'base64'), |
| 41 | + // iso: (str) => iso.Rfc4648.base64.decode(str), |
| 42 | + // scure: (str) => scure.base64.decode(str), |
| 43 | + // web: (str) => Uint8Array.fromBase64(str), |
| 44 | + // }, |
| 45 | + // }, |
33 | 46 |
|
34 | | - UTF8: { |
35 | | - encode: { |
36 | | - node: (buf) => Buffer.from(buf).toString('utf8'), |
37 | | - iso: (buf) => iso.utf8.encode(buf), |
38 | | - }, |
39 | | - decode: { |
40 | | - node: (str) => Buffer.from(str, 'utf8'), |
41 | | - iso: (str) => iso.utf8.decode(str), |
42 | | - }, |
43 | | - }, |
| 47 | + // UTF8: { |
| 48 | + // encode: { |
| 49 | + // node: (buf) => Buffer.from(buf).toString('utf8'), |
| 50 | + // iso: (buf) => iso.UTF8.utf8.encode(buf), |
| 51 | + // }, |
| 52 | + // decode: { |
| 53 | + // node: (str) => Buffer.from(str, 'utf8'), |
| 54 | + // iso: (str) => iso.UTF8.utf8.decode(str), |
| 55 | + // }, |
| 56 | + // }, |
44 | 57 | } |
45 | 58 |
|
46 | 59 | // buffer title, sample count, data |
47 | 60 | const buffers = { |
48 | | - '32 B': [20_000, new Uint8Array(32).fill(1)], |
49 | | - '64 B': [20_000, new Uint8Array(64).fill(1)], |
50 | | - '1 KB': [500, new Uint8Array(1024).fill(2)], |
51 | | - '8 KB': [10, new Uint8Array(1024 * 8).fill(3)], |
| 61 | + '32 B': new Uint8Array(32).fill(1), |
| 62 | + '64 B': new Uint8Array(64).fill(1), |
| 63 | + '1 KB': new Uint8Array(1024).fill(2), |
| 64 | + '8 KB': new Uint8Array(1024 * 8).fill(3), |
| 65 | +} |
| 66 | +const strs = { |
| 67 | + '32 B': iso.Rfc4648.hex.encode(new Uint8Array(32).fill(1)), |
| 68 | + '64 B': iso.Rfc4648.hex.encode(new Uint8Array(64).fill(1)), |
| 69 | + '1 KB': iso.Rfc4648.hex.encode(new Uint8Array(1024).fill(2)), |
| 70 | + '8 KB': iso.Rfc4648.hex.encode(new Uint8Array(1024 * 8).fill(3)), |
| 71 | +} |
| 72 | + |
| 73 | +const parseSize = (sizeStr) => { |
| 74 | + const match = sizeStr.match(/^(\d+)\s*(B|KB)$/) |
| 75 | + if (!match) return 0 |
| 76 | + const value = parseInt(match[1], 10) |
| 77 | + const unit = match[2] |
| 78 | + return unit === 'KB' ? value * 1024 : value |
52 | 79 | } |
53 | 80 |
|
54 | | -const main = () => |
55 | | - bench.run(async () => { |
56 | | - for (const [k, libs] of Object.entries(codecs)) { |
57 | | - console.log(`==== ${k} ====`) |
58 | | - for (const [size, [samples, buf]] of Object.entries(buffers)) { |
59 | | - // encode |
60 | | - for (const [lib, fn] of Object.entries(libs.encode)) |
61 | | - await bench.mark(`${k} (encode) ${size} ${lib}`, samples, () => |
62 | | - fn(buf) |
63 | | - ) |
64 | | - console.log() |
| 81 | +const main = async () => { |
| 82 | + const sortedSizes = Object.keys(buffers).sort( |
| 83 | + (a, b) => parseSize(a) - parseSize(b) |
| 84 | + ) |
| 85 | + |
| 86 | + for (const size of sortedSizes) { |
| 87 | + console.log(`==== ${size} ====`) |
| 88 | + const buf = buffers[size] |
| 89 | + const str = strs[size] |
65 | 90 |
|
66 | | - // decode |
67 | | - const str = libs.encode.iso(buf) |
68 | | - for (const [lib, fn] of Object.entries(libs.decode)) |
69 | | - await bench.mark(`${k} (decode) ${size} ${lib}`, samples, () => |
70 | | - fn(str) |
71 | | - ) |
72 | | - console.log() |
| 91 | + // All encodes and decodes for all codecs in one bench |
| 92 | + const bench = new Bench({ time: 10 }) |
| 93 | + for (const [codecName, libs] of Object.entries(codecs)) { |
| 94 | + for (const [lib, fn] of Object.entries(libs.encode)) { |
| 95 | + bench.add(`${codecName} (encode) ${size} ${lib}`, () => fn(buf)) |
| 96 | + } |
| 97 | + for (const [lib, fn] of Object.entries(libs.decode)) { |
| 98 | + bench.add(`${codecName} (decode) ${size} ${lib}`, () => fn(str)) |
73 | 99 | } |
74 | 100 | } |
75 | | - // Log current RAM |
76 | | - bench.logMem() |
77 | | - }) |
| 101 | + await bench.run() |
| 102 | + console.table(bench.table()) |
| 103 | + console.log() |
| 104 | + } |
| 105 | +} |
78 | 106 |
|
79 | 107 | main() |
0 commit comments