diff --git a/benchmark/index.js b/benchmark/index.js new file mode 100644 index 00000000..87f72ba1 --- /dev/null +++ b/benchmark/index.js @@ -0,0 +1,83 @@ +// taken from https://github.com/Rich-Harris/superjson-and-devalue + +import ARSON from "arson"; +import { parse, stringify, uneval } from "devalue"; +import c from "kleur"; +import * as superjson from "superjson"; +import { createTson, tsonDate, tsonRegExp, tsonSet } from "tupleson"; + +const obj = { + array: [{ foo: 1 }, { bar: 2 }, { baz: 3 }], + date: new Date(), + number: 42, + regex: /the quick brown fox/, + set: new Set([1, 2, 3]), + xss: '', +}; + +// circular references are not supported by tupleson +// obj.self = obj; + +const tson = createTson({ + types: [tsonDate, tsonRegExp, tsonSet], +}); + +const superjson_serialized = superjson.stringify(obj); +const devalue_unevaled = uneval(obj); +const devalue_stringified = stringify(obj); +const arson_stringified = ARSON.stringify(obj); +const tson_serialized = tson.stringify(obj); + +console.log( + `superjson output: ${c.bold().cyan(superjson_serialized.length)} bytes`, +); + +console.log(`tson output: ${c.bold().cyan(tson_serialized.length)} bytes`); +// console.log(superjson_serialized); +console.log( + `devalue.uneval output: ${c.bold().cyan(devalue_unevaled.length)} bytes`, +); +// console.log(devalue_unevaled); +console.log( + `devalue.stringify output: ${c + .bold() + .cyan(devalue_stringified.length)} bytes`, +); +// console.log(devalue_stringified); +console.log(`arson output: ${c.bold().cyan(arson_stringified.length)} bytes`); +// console.log(arson_stringified); + +// const superjson_deserialized = superjson.parse(superjson_serialized); +// const devalue_deserialized = eval(`(${devalue_unevaled})`); + +const iterations = 1e6; + +function test(fn, label = fn.toString()) { + const start = Date.now(); + console.log(); + console.log(c.bold(label)); + let i = iterations; + while (i--) { + fn(); + } + + console.log( + `${iterations} iterations in ${c.bold().cyan(Date.now() - start)}ms`, + ); +} + +// serialization +test(() => superjson.stringify(obj)); +test(() => tson.stringify(obj)); +test(() => uneval(obj)); +test(() => stringify(obj)); +test(() => ARSON.stringify(obj)); + +// deserialization +test(() => superjson.parse(superjson_serialized)); +test(() => tson.parse(tson_serialized)); +test(() => eval(`(${devalue_unevaled})`)); +test(() => ARSON.parse(arson_stringified)); +test(() => parse(devalue_stringified)); + +console.log(); diff --git a/benchmark/package.json b/benchmark/package.json new file mode 100644 index 00000000..9431843b --- /dev/null +++ b/benchmark/package.json @@ -0,0 +1,20 @@ +{ + "name": "@tupleson/benchmark", + "version": "0.0.0", + "private": true, + "description": "benchmark", + "license": "MIT", + "type": "module", + "scripts": { + "postinstall": "cd ../ && pnpm run build", + "start": "node index.js" + }, + "dependencies": { + "arson": "^0.2.6", + "devalue": "^4.0.0", + "kleur": "^4.0.2", + "superjson": "^1.9.1", + "tupleson": "latest" + }, + "devDependencies": {} +} diff --git a/cspell.json b/cspell.json index 4bf47fb1..60c818f7 100644 --- a/cspell.json +++ b/cspell.json @@ -14,8 +14,10 @@ "commitlint", "contributorsrc", "conventionalcommits", + "deferreds", "Iterarable", "KATT", + "kleur", "knip", "lcov", "markdownlintignore", @@ -24,10 +26,11 @@ "packagejson", "quickstart", "stringifier", + "superjson", "tson", "tsup", "tupleson", - "wontfix", - "deferreds" + "unevaled", + "wontfix" ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db94073c..a3bb95c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,6 +126,24 @@ importers: specifier: ^1.2.2 version: 1.2.2 + benchmark: + dependencies: + arson: + specifier: ^0.2.6 + version: 0.2.6 + devalue: + specifier: ^4.0.0 + version: 4.3.2 + kleur: + specifier: ^4.0.2 + version: 4.1.5 + superjson: + specifier: ^1.9.1 + version: 1.13.3 + tupleson: + specifier: link:.. + version: link:.. + examples/async: devDependencies: '@types/node': @@ -1620,6 +1638,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /arson@0.2.6: + resolution: {integrity: sha512-wVRnIfjOaCWu3jrf3j1CU/eotDf7tuM34cBswo32EwyLPaMiaWgETfROdYVv47VWEbWSOaZaDnkypGQtQduLbw==} + dev: false + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true @@ -2213,6 +2235,13 @@ packages: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true + /copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.15 + dev: false + /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true @@ -2529,6 +2558,10 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /devalue@4.3.2: + resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} + dev: false + /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4064,6 +4097,11 @@ packages: call-bind: 1.0.2 dev: true + /is-what@4.1.15: + resolution: {integrity: sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==} + engines: {node: '>=12.13'} + dev: false + /is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} @@ -4260,6 +4298,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + /knip@2.31.0: resolution: {integrity: sha512-Axy7cLkKbD4IWMzhw1I6HaZMGRFbVY9zhr5AdM4TZuS93RdqxbdPJQcLInw8RSF+uymfwYHdjFpPsOMa4di1HA==} engines: {node: '>=16.17.0 <17 || >=18.6.0'} @@ -6143,6 +6186,13 @@ packages: resolution: {integrity: sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==} dev: true + /superjson@1.13.3: + resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} + engines: {node: '>=10'} + dependencies: + copy-anything: 3.0.5 + dev: false + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 591cd1ce..de0f7766 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,3 +2,4 @@ packages: - ./ - "examples/*" - "examples/.*/*" + - "benchmark" \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts index d2860757..27b62ac9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ include: ["src"], reporter: ["html", "lcov"], }, - exclude: ["lib", "node_modules", "examples"], + exclude: ["lib", "node_modules", "examples", "benchmark"], setupFiles: ["console-fail-test/setup"], }, });