From fd39bb16e894ee1cad6816a7130fb99b23de9923 Mon Sep 17 00:00:00 2001 From: Vladislav Mamon Date: Mon, 24 Jan 2022 11:08:01 +0500 Subject: [PATCH] perf(no-release): add benchmarks Added a couple of real-world-ish benchmarks with Sigma and Parjs: - JSON parser. - Tuple parser. --- benchmarks/README.md | 29 + benchmarks/package-lock.json | 797 +++++++++++++++++++++++++++ benchmarks/package.json | 23 + benchmarks/src/index.ts | 2 + benchmarks/src/json/@sample.ts | 924 ++++++++++++++++++++++++++++++++ benchmarks/src/json/ast.ts | 38 ++ benchmarks/src/json/index.ts | 20 + benchmarks/src/json/parjs.ts | 179 +++++++ benchmarks/src/json/sigma.ts | 170 ++++++ benchmarks/src/tuple/@sample.ts | 1 + benchmarks/src/tuple/ast.ts | 9 + benchmarks/src/tuple/index.ts | 20 + benchmarks/src/tuple/parjs.ts | 50 ++ benchmarks/src/tuple/sigma.ts | 64 +++ benchmarks/tsconfig.json | 11 + tsconfig.json | 2 +- 16 files changed, 2338 insertions(+), 1 deletion(-) create mode 100644 benchmarks/README.md create mode 100644 benchmarks/package-lock.json create mode 100644 benchmarks/package.json create mode 100644 benchmarks/src/index.ts create mode 100644 benchmarks/src/json/@sample.ts create mode 100644 benchmarks/src/json/ast.ts create mode 100644 benchmarks/src/json/index.ts create mode 100644 benchmarks/src/json/parjs.ts create mode 100644 benchmarks/src/json/sigma.ts create mode 100644 benchmarks/src/tuple/@sample.ts create mode 100644 benchmarks/src/tuple/ast.ts create mode 100644 benchmarks/src/tuple/index.ts create mode 100644 benchmarks/src/tuple/parjs.ts create mode 100644 benchmarks/src/tuple/sigma.ts create mode 100644 benchmarks/tsconfig.json diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000..b11ef00 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,29 @@ +# Benchmarks + +Here you will find some benchmarks and rough performance comparison with similar libraries. + +## Notes + +Unfortunately, it's difficult to come up with sensible benchmarks, given that how a parser written with **sigma** depends entirely on what you are parsing, how you structure your parser(s), which patterns the parser attempts to match first, what is involved in constructing your AST (if any), and so on. + +All that said, here are some rough numbers from the [JSON parsing benchmark][json-bench] (running on my MacBook Pro 16" with `Intel i9-9880H @ 2.30GHz` and `Node@14`). + +```hs +Running "JSON :: sigma vs parjs" suite... + + sigma: 582 ops/s, ±1.12% | fastest + parjs: 138 ops/s, ±1.38% | slowest, 76.29% slower +``` + +I have included results from [Sigma] and [Parjs] (another parser combinator library). I wanted to also add [Arcsecond], because I like its API with functional flavor, but somehow their JSON example is _atrociously_ slow (like, orders of magnitude, 250-500 times slower). + +The [JSON sample][json-sample] being parsed is a typical JSON data, which has 923 lines. This translates to ~530k lines of JSON per second, and that is actually on par with some Rust parser combinator crates like [pom]. + + + +[json-bench]: ./src/json +[json-sample]: ./src/json/@sample.ts +[sigma]: https://github.com/norskeld/sigma +[parjs]: https://github.com/GregRos/parjs +[arcsecond]: https://github.com/francisrstokes/arcsecond +[pom]: https://github.com/J-F-Liu/pom diff --git a/benchmarks/package-lock.json b/benchmarks/package-lock.json new file mode 100644 index 0000000..2183947 --- /dev/null +++ b/benchmarks/package-lock.json @@ -0,0 +1,797 @@ +{ + "name": "@nrsk/sigma-benchmarks", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@nrsk/sigma-benchmarks", + "version": "1.0.0", + "dependencies": { + "@nrsk/sigma": "2.0.0", + "benny": "^3.7.1", + "parjs": "0.12.7" + }, + "devDependencies": { + "@types/benchmark": "^2.1.1", + "@types/node": "^14.18.0", + "typescript": "^4.5.5" + } + }, + "node_modules/@arrows/array": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", + "integrity": "sha512-MGYS8xi3c4tTy1ivhrVntFvufoNzje0PchjEz6G/SsWRgUKxL4tKwS6iPdO8vsaJYldagAeWMd5KRD0aX3Q39g==", + "dependencies": { + "@arrows/composition": "^1.2.2" + } + }, + "node_modules/@arrows/composition": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@arrows/composition/-/composition-1.2.2.tgz", + "integrity": "sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ==" + }, + "node_modules/@arrows/dispatch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@arrows/dispatch/-/dispatch-1.0.3.tgz", + "integrity": "sha512-v/HwvrFonitYZM2PmBlAlCqVqxrkIIoiEuy5bQgn0BdfvlL0ooSBzcPzTMrtzY8eYktPyYcHg8fLbSgyybXEqw==", + "dependencies": { + "@arrows/composition": "^1.2.2" + } + }, + "node_modules/@arrows/error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@arrows/error/-/error-1.0.2.tgz", + "integrity": "sha512-yvkiv1ay4Z3+Z6oQsUkedsQm5aFdyPpkBUQs8vejazU/RmANABx6bMMcBPPHI4aW43VPQmXFfBzr/4FExwWTEA==" + }, + "node_modules/@arrows/multimethod": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@arrows/multimethod/-/multimethod-1.4.1.tgz", + "integrity": "sha512-AZnAay0dgPnCJxn3We5uKiB88VL+1ZIF2SjZohLj6vqY2UyvB/sKdDnFP+LZNVsTC5lcnGPmLlRRkAh4sXkXsQ==", + "dependencies": { + "@arrows/array": "^1.4.1", + "@arrows/composition": "^1.2.2", + "@arrows/error": "^1.0.2", + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/@nrsk/sigma": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nrsk/sigma/-/sigma-2.0.0.tgz", + "integrity": "sha512-KC8agPrIBwmCH7Ws63GUOwwaXWGMJVoyXzazdd+4BmEvJJ8SU6bARgnvasErwn2aMztqYrnAYQQHydeUMI81Yw==", + "engines": { + "node": ">=14.17.0" + } + }, + "node_modules/@types/benchmark": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/benchmark/-/benchmark-2.1.1.tgz", + "integrity": "sha512-XmdNOarpSSxnb3DE2rRFOFsEyoqXLUL+7H8nSGS25vs+JS0018bd+cW5Ma9vdlkPmoTHSQ6e8EUFMFMxeE4l+g==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.18.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz", + "integrity": "sha512-j11XSuRuAlft6vLDEX4RvhqC0KxNxx6QIyMXNb0vHHSNPXTPeiy3algESWmOOIzEtiEL0qiowPU3ewW9hHVa7Q==", + "dev": true + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "dependencies": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "node_modules/benny": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/benny/-/benny-3.7.1.tgz", + "integrity": "sha512-USzYxODdVfOS7JuQq/L0naxB788dWCiUgUTxvN+WLPt/JfcDURNNj8kN/N+uK6PDvuR67/9/55cVKGPleFQINA==", + "dependencies": { + "@arrows/composition": "^1.0.0", + "@arrows/dispatch": "^1.0.2", + "@arrows/multimethod": "^1.1.6", + "benchmark": "^2.1.4", + "common-tags": "^1.8.0", + "fs-extra": "^10.0.0", + "json2csv": "^5.0.6", + "kleur": "^4.1.4", + "log-update": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/char-info": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/char-info/-/char-info-0.3.2.tgz", + "integrity": "sha512-6P6KW8crZx+N857wZalB4FreR+PhheSLmAk22c8zbQsFhsDxZP1aTDfmOjrzddgp1IBOl53b0Z8kDQrwh4B//A==", + "dependencies": { + "node-interval-tree": "^1.3.3" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/json2csv": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.6.tgz", + "integrity": "sha512-0/4Lv6IenJV0qj2oBdgPIAmFiKKnh8qh7bmLFJ+/ZZHLjSeiL3fKKGX3UryvKPbxFbhV+JcYo9KUC19GJ/Z/4A==", + "dependencies": { + "commander": "^6.1.0", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + }, + "bin": { + "json2csv": "bin/json2csv.js" + }, + "engines": { + "node": ">= 10", + "npm": ">= 6.13.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/kleur": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", + "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/node-interval-tree": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-interval-tree/-/node-interval-tree-1.3.3.tgz", + "integrity": "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==", + "dependencies": { + "shallowequal": "^1.0.2" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parjs": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/parjs/-/parjs-0.12.7.tgz", + "integrity": "sha512-aKw+vsSMBdZNdxcetIwi5mnmFckuwxTz7dKu07wEzrNjKYtvhRlrlla3b4GAEmGMyAWhrocLrUcbSGvmMZMU3Q==", + "dependencies": { + "char-info": "^0.3.1", + "lodash": "^4.17.13" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + } + }, + "dependencies": { + "@arrows/array": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", + "integrity": "sha512-MGYS8xi3c4tTy1ivhrVntFvufoNzje0PchjEz6G/SsWRgUKxL4tKwS6iPdO8vsaJYldagAeWMd5KRD0aX3Q39g==", + "requires": { + "@arrows/composition": "^1.2.2" + } + }, + "@arrows/composition": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@arrows/composition/-/composition-1.2.2.tgz", + "integrity": "sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ==" + }, + "@arrows/dispatch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@arrows/dispatch/-/dispatch-1.0.3.tgz", + "integrity": "sha512-v/HwvrFonitYZM2PmBlAlCqVqxrkIIoiEuy5bQgn0BdfvlL0ooSBzcPzTMrtzY8eYktPyYcHg8fLbSgyybXEqw==", + "requires": { + "@arrows/composition": "^1.2.2" + } + }, + "@arrows/error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@arrows/error/-/error-1.0.2.tgz", + "integrity": "sha512-yvkiv1ay4Z3+Z6oQsUkedsQm5aFdyPpkBUQs8vejazU/RmANABx6bMMcBPPHI4aW43VPQmXFfBzr/4FExwWTEA==" + }, + "@arrows/multimethod": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@arrows/multimethod/-/multimethod-1.4.1.tgz", + "integrity": "sha512-AZnAay0dgPnCJxn3We5uKiB88VL+1ZIF2SjZohLj6vqY2UyvB/sKdDnFP+LZNVsTC5lcnGPmLlRRkAh4sXkXsQ==", + "requires": { + "@arrows/array": "^1.4.1", + "@arrows/composition": "^1.2.2", + "@arrows/error": "^1.0.2", + "fast-deep-equal": "^3.1.3" + } + }, + "@nrsk/sigma": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nrsk/sigma/-/sigma-2.0.0.tgz", + "integrity": "sha512-KC8agPrIBwmCH7Ws63GUOwwaXWGMJVoyXzazdd+4BmEvJJ8SU6bARgnvasErwn2aMztqYrnAYQQHydeUMI81Yw==" + }, + "@types/benchmark": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/benchmark/-/benchmark-2.1.1.tgz", + "integrity": "sha512-XmdNOarpSSxnb3DE2rRFOFsEyoqXLUL+7H8nSGS25vs+JS0018bd+cW5Ma9vdlkPmoTHSQ6e8EUFMFMxeE4l+g==", + "dev": true + }, + "@types/node": { + "version": "14.18.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz", + "integrity": "sha512-j11XSuRuAlft6vLDEX4RvhqC0KxNxx6QIyMXNb0vHHSNPXTPeiy3algESWmOOIzEtiEL0qiowPU3ewW9hHVa7Q==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + }, + "benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "requires": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "benny": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/benny/-/benny-3.7.1.tgz", + "integrity": "sha512-USzYxODdVfOS7JuQq/L0naxB788dWCiUgUTxvN+WLPt/JfcDURNNj8kN/N+uK6PDvuR67/9/55cVKGPleFQINA==", + "requires": { + "@arrows/composition": "^1.0.0", + "@arrows/dispatch": "^1.0.2", + "@arrows/multimethod": "^1.1.6", + "benchmark": "^2.1.4", + "common-tags": "^1.8.0", + "fs-extra": "^10.0.0", + "json2csv": "^5.0.6", + "kleur": "^4.1.4", + "log-update": "^4.0.0" + } + }, + "char-info": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/char-info/-/char-info-0.3.2.tgz", + "integrity": "sha512-6P6KW8crZx+N857wZalB4FreR+PhheSLmAk22c8zbQsFhsDxZP1aTDfmOjrzddgp1IBOl53b0Z8kDQrwh4B//A==", + "requires": { + "node-interval-tree": "^1.3.3" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "json2csv": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.6.tgz", + "integrity": "sha512-0/4Lv6IenJV0qj2oBdgPIAmFiKKnh8qh7bmLFJ+/ZZHLjSeiL3fKKGX3UryvKPbxFbhV+JcYo9KUC19GJ/Z/4A==", + "requires": { + "commander": "^6.1.0", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "kleur": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", + "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "node-interval-tree": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-interval-tree/-/node-interval-tree-1.3.3.tgz", + "integrity": "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==", + "requires": { + "shallowequal": "^1.0.2" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "parjs": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/parjs/-/parjs-0.12.7.tgz", + "integrity": "sha512-aKw+vsSMBdZNdxcetIwi5mnmFckuwxTz7dKu07wEzrNjKYtvhRlrlla3b4GAEmGMyAWhrocLrUcbSGvmMZMU3Q==", + "requires": { + "char-info": "^0.3.1", + "lodash": "^4.17.13" + } + }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } +} diff --git a/benchmarks/package.json b/benchmarks/package.json new file mode 100644 index 0000000..36cec8a --- /dev/null +++ b/benchmarks/package.json @@ -0,0 +1,23 @@ +{ + "version": "1.0.0", + "name": "@nrsk/sigma-benchmarks", + "description": "Benchmarks for @nrsk/sigma", + "private": true, + "scripts": { + "bench:all": "node dist/benchmarks/src/index.js", + "bench:json": "node dist/benchmarks/src/json/index.js", + "bench:tuple": "node dist/benchmarks/src/tuple/index.js", + "build": "tsc -p tsconfig.json", + "start": "npm run build && npm run bench:all" + }, + "dependencies": { + "@nrsk/sigma": "2.0.0", + "benny": "^3.7.1", + "parjs": "0.12.7" + }, + "devDependencies": { + "@types/benchmark": "^2.1.1", + "@types/node": "^14.18.0", + "typescript": "^4.5.5" + } +} diff --git a/benchmarks/src/index.ts b/benchmarks/src/index.ts new file mode 100644 index 0000000..a91e2c3 --- /dev/null +++ b/benchmarks/src/index.ts @@ -0,0 +1,2 @@ +import './json' +import './tuple' diff --git a/benchmarks/src/json/@sample.ts b/benchmarks/src/json/@sample.ts new file mode 100644 index 0000000..c167b7c --- /dev/null +++ b/benchmarks/src/json/@sample.ts @@ -0,0 +1,924 @@ +export const SAMPLE = ` +[ + { + "_id": "61ed767b81b27892241cb472", + "index": 0, + "guid": "ce169efe-06e1-414d-bd56-ff217d482105", + "isActive": false, + "balance": "$1,842.71", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "green", + "name": "Michele Lyons", + "gender": "female", + "company": "PETICULAR", + "email": "michelelyons@peticular.com", + "phone": "+1 (823) 590-3979", + "address": "667 Gilmore Court, Farmers, Illinois, 3879", + "about": "Culpa qui non fugiat adipisicing deserunt. Occaecat reprehenderit occaecat id minim eiusmod. Incididunt cillum adipisicing minim magna officia laborum duis esse. Amet in aliquip adipisicing eiusmod sint dolore minim sint aute eu fugiat proident quis. Incididunt voluptate dolore Lorem occaecat mollit ex anim. Commodo aliqua excepteur proident magna et.\r\n", + "registered": "2018-11-15T06:55:56 -05:00", + "latitude": -79.733944, + "longitude": 155.272629, + "tags": [ + "aute", + "ipsum", + "reprehenderit", + "proident", + "dolore", + "qui", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Madelyn Oconnor" + }, + { + "id": 1, + "name": "Faith Larsen" + }, + { + "id": 2, + "name": "Rose Pugh" + } + ], + "greeting": "Hello, Michele Lyons! You have 1 unread messages.", + "favoriteFruit": "banana", + "github": "https://github.com/Marla/245" + }, + { + "_id": "61ed767bbd99889d797c3498", + "index": 1, + "guid": "45001249-0a9d-423e-b73d-3f8277f07add", + "isActive": false, + "balance": "$2,934.41", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "brown", + "name": "Reed Daniels", + "gender": "male", + "company": "PETIGEMS", + "email": "reeddaniels@petigems.com", + "phone": "+1 (829) 517-2737", + "address": "117 Brighton Avenue, Bascom, Indiana, 4874", + "about": "Nisi sit aute do laboris consequat. Eiusmod deserunt eiusmod officia non exercitation duis esse in irure tempor aliquip. Do tempor commodo esse sint deserunt esse deserunt dolor amet dolor ullamco eu. Consequat id laboris anim tempor esse incididunt nulla. Esse veniam dolore non quis ea sint commodo. Voluptate aute aliqua adipisicing esse eu qui do deserunt est sit. Cillum consequat deserunt nulla ut esse excepteur reprehenderit eu minim eiusmod deserunt ullamco aliquip.\r\n", + "registered": "2017-11-10T05:06:43 -05:00", + "latitude": 54.988347, + "longitude": -167.535251, + "tags": [ + "eiusmod", + "ex", + "aliquip", + "adipisicing", + "cillum", + "do", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Maggie English" + }, + { + "id": 1, + "name": "Burns Macdonald" + }, + { + "id": 2, + "name": "Garcia Moody" + } + ], + "greeting": "Hello, Reed Daniels! You have 2 unread messages.", + "favoriteFruit": "strawberry", + "github": "https://github.com/Renee/852" + }, + { + "_id": "61ed767bd71f0b2085cde17f", + "index": 2, + "guid": "a9fc68de-c10c-4c87-a2f6-9f3cc5d55eee", + "isActive": true, + "balance": "$3,525.75", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "green", + "name": "Britney Dickson", + "gender": "female", + "company": "MATRIXITY", + "email": "britneydickson@matrixity.com", + "phone": "+1 (810) 422-3829", + "address": "179 Indiana Place, Harrodsburg, Colorado, 9532", + "about": "Ex in culpa fugiat et occaecat nisi ad. Laborum consectetur Lorem est minim eiusmod incididunt aliqua sint sint. Enim quis esse magna consequat irure.\r\n", + "registered": "2014-04-27T10:31:08 -06:00", + "latitude": -54.022594, + "longitude": -174.769598, + "tags": [ + "anim", + "occaecat", + "amet", + "exercitation", + "cillum", + "magna", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Vivian Erickson" + }, + { + "id": 1, + "name": "Marci Hewitt" + }, + { + "id": 2, + "name": "Alyce Parker" + } + ], + "greeting": "Hello, Britney Dickson! You have 4 unread messages.", + "favoriteFruit": "strawberry", + "github": null + }, + { + "_id": "61ed767b100818a787f87bed", + "index": 3, + "guid": "8034422c-a376-4580-9459-3e643b4e090c", + "isActive": false, + "balance": "$2,071.32", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "blue", + "name": "Nieves Griffith", + "gender": "male", + "company": "ACCUSAGE", + "email": "nievesgriffith@accusage.com", + "phone": "+1 (888) 559-3578", + "address": "449 Hawthorne Street, Manchester, Rhode Island, 8469", + "about": "Consectetur fugiat dolore et commodo irure commodo nulla ea dolore et mollit laborum eu ex. Minim sit est nisi commodo dolore ea aliquip officia. Occaecat non quis do do ad do qui minim adipisicing cillum dolore mollit elit non. Esse quis eu laborum aute aliquip velit ea fugiat culpa minim quis deserunt. Cillum voluptate esse dolor ex exercitation dolore ipsum eu reprehenderit laboris quis commodo minim officia. Esse velit voluptate commodo commodo proident minim dolore ullamco pariatur aliquip culpa non.\r\n", + "registered": "2019-05-16T03:38:52 -05:00", + "latitude": 12.530648, + "longitude": -18.362477, + "tags": [ + "commodo", + "culpa", + "cillum", + "aute", + "commodo", + "sunt", + "sit" + ], + "friends": [ + { + "id": 0, + "name": "Delaney Sampson" + }, + { + "id": 1, + "name": "Dolores Zimmerman" + }, + { + "id": 2, + "name": "Avila Paul" + } + ], + "greeting": "Hello, Nieves Griffith! You have 2 unread messages.", + "favoriteFruit": "banana", + "github": "https://github.com/Celina/505" + }, + { + "_id": "61ed767b1740b07364d01668", + "index": 4, + "guid": "3821fe58-b362-4aac-8f62-18160fb232cd", + "isActive": false, + "balance": "$3,077.09", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "blue", + "name": "Mona Lucas", + "gender": "female", + "company": "GEEKFARM", + "email": "monalucas@geekfarm.com", + "phone": "+1 (928) 455-3852", + "address": "178 Lefferts Avenue, Martell, Alabama, 2052", + "about": "Non enim pariatur id occaecat eiusmod voluptate pariatur aliquip nisi irure magna non consectetur. Consequat sit duis dolor esse quis duis veniam eiusmod elit Lorem quis qui laborum laboris. Culpa aliquip proident ea cupidatat irure nostrud consequat occaecat dolor tempor fugiat occaecat voluptate. Excepteur ut eiusmod veniam nulla sint elit magna velit id occaecat. Est nulla id fugiat ad occaecat.\r\n", + "registered": "2015-09-23T10:29:36 -05:00", + "latitude": -0.38082, + "longitude": -1.315733, + "tags": [ + "deserunt", + "dolore", + "ipsum", + "sunt", + "occaecat", + "pariatur", + "ad" + ], + "friends": [ + { + "id": 0, + "name": "Duffy Dixon" + }, + { + "id": 1, + "name": "Shepherd Stokes" + }, + { + "id": 2, + "name": "Wells Spencer" + } + ], + "greeting": "Hello, Mona Lucas! You have 7 unread messages.", + "favoriteFruit": "apple", + "github": null + }, + { + "_id": "61ed767b17a52efa2e97d2ac", + "index": 5, + "guid": "a32efe32-c150-4be0-833c-d74846efc900", + "isActive": false, + "balance": "$3,492.29", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "blue", + "name": "Marylou Hawkins", + "gender": "female", + "company": "OCEANICA", + "email": "marylouhawkins@oceanica.com", + "phone": "+1 (925) 547-3020", + "address": "975 Hazel Court, Rivers, Nevada, 3246", + "about": "Dolor incididunt magna nostrud fugiat. Veniam occaecat non cillum ipsum in dolor aliqua sunt Lorem consequat esse ex consectetur commodo. Elit ea consectetur dolor eiusmod dolor aute exercitation occaecat sint culpa proident ullamco est. Eu sunt fugiat do commodo ut adipisicing fugiat excepteur ut laboris laboris qui eu minim. Exercitation aute sint duis consequat. Fugiat dolor adipisicing incididunt dolore exercitation est nostrud sunt commodo officia ex. Anim pariatur pariatur ut Lorem voluptate.\r\n", + "registered": "2019-02-24T07:21:36 -05:00", + "latitude": -31.640517, + "longitude": 67.594811, + "tags": [ + "qui", + "id", + "mollit", + "excepteur", + "nulla", + "exercitation", + "ipsum" + ], + "friends": [ + { + "id": 0, + "name": "Armstrong Rush" + }, + { + "id": 1, + "name": "Green Noble" + }, + { + "id": 2, + "name": "Jewel Woods" + } + ], + "greeting": "Hello, Marylou Hawkins! You have 8 unread messages.", + "favoriteFruit": "strawberry", + "github": "https://github.com/English/796" + }, + { + "_id": "61ed767bc71002cb31556952", + "index": 6, + "guid": "105349a1-db77-4ff1-9ae9-b0eb3d660a0b", + "isActive": false, + "balance": "$1,997.53", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Joy Conway", + "gender": "female", + "company": "EMPIRICA", + "email": "joyconway@empirica.com", + "phone": "+1 (895) 522-3021", + "address": "759 Bassett Avenue, Eggertsville, California, 1820", + "about": "Consectetur dolor ut id quis anim ad pariatur proident duis. Reprehenderit ullamco ea labore adipisicing eiusmod sit velit veniam nisi eiusmod excepteur sunt ipsum. Velit cillum veniam aute qui ea et et proident incididunt.\r\n", + "registered": "2019-08-08T12:04:16 -05:00", + "latitude": 35.510935, + "longitude": 176.323185, + "tags": [ + "eiusmod", + "non", + "velit", + "ex", + "cupidatat", + "consequat", + "eiusmod" + ], + "friends": [ + { + "id": 0, + "name": "Lara Day" + }, + { + "id": 1, + "name": "Campbell Bonner" + }, + { + "id": 2, + "name": "Velma Mueller" + } + ], + "greeting": "Hello, Joy Conway! You have 9 unread messages.", + "favoriteFruit": "banana", + "github": "https://github.com/Naomi/136" + }, + { + "_id": "61ed767bc493ff5a5b7783b6", + "index": 7, + "guid": "d396b8c6-0ec8-4a73-af50-803763e9e618", + "isActive": false, + "balance": "$1,330.75", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "brown", + "name": "Avery Douglas", + "gender": "male", + "company": "BILLMED", + "email": "averydouglas@billmed.com", + "phone": "+1 (959) 420-2759", + "address": "873 Everit Street, Davenport, Alaska, 6359", + "about": "Proident non labore aliquip culpa nisi ullamco anim excepteur occaecat. Lorem laboris ad tempor pariatur. Consectetur irure officia labore eu et cupidatat velit. Ea velit tempor minim officia aute duis amet dolore laboris cupidatat. Proident sint nisi magna cupidatat amet labore et Lorem velit.\r\n", + "registered": "2020-02-01T10:50:35 -05:00", + "latitude": 83.882091, + "longitude": -128.188732, + "tags": [ + "laborum", + "aliquip", + "elit", + "reprehenderit", + "ad", + "aliqua", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Glover Padilla" + }, + { + "id": 1, + "name": "Wall Goff" + }, + { + "id": 2, + "name": "Malinda Snyder" + } + ], + "greeting": "Hello, Avery Douglas! You have 1 unread messages.", + "favoriteFruit": "banana", + "github": "https://github.com/Stephanie/734" + }, + { + "_id": "61ed767b76acf9fc0e6faea4", + "index": 8, + "guid": "b872f4e1-39e6-43d9-88f1-5539437402f9", + "isActive": false, + "balance": "$1,200.26", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "green", + "name": "Becker Wells", + "gender": "male", + "company": "GLASSTEP", + "email": "beckerwells@glasstep.com", + "phone": "+1 (977) 421-2258", + "address": "264 Saratoga Avenue, Mapletown, South Dakota, 9757", + "about": "Cillum sit Lorem voluptate dolor exercitation ullamco id amet nulla. Consequat et magna ullamco eu officia nulla aliqua. Consectetur voluptate nisi ullamco nisi elit consequat aute amet occaecat eu ipsum magna in.\r\n", + "registered": "2019-05-23T02:59:56 -05:00", + "latitude": 36.984307, + "longitude": 85.66017, + "tags": [ + "Lorem", + "id", + "anim", + "mollit", + "anim", + "quis", + "labore" + ], + "friends": [ + { + "id": 0, + "name": "Clare Solis" + }, + { + "id": 1, + "name": "Knox Lindsay" + }, + { + "id": 2, + "name": "Lawrence Orr" + } + ], + "greeting": "Hello, Becker Wells! You have 3 unread messages.", + "favoriteFruit": "apple", + "github": "https://github.com/Juliette/280" + }, + { + "_id": "61ed767bb68e44f7f1f35e2f", + "index": 9, + "guid": "f8eaa776-0c98-4778-83ee-abb4438613dc", + "isActive": false, + "balance": "$3,458.82", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Berry Hanson", + "gender": "male", + "company": "SYNKGEN", + "email": "berryhanson@synkgen.com", + "phone": "+1 (899) 532-3613", + "address": "654 Sedgwick Street, Woodlands, Louisiana, 8461", + "about": "Exercitation ut ut Lorem fugiat fugiat elit do quis consectetur. Ad ullamco sint ad commodo in velit ipsum in qui ullamco reprehenderit anim dolore. Incididunt consequat ut culpa ipsum et ad ad mollit ea. Aute elit do veniam incididunt eiusmod ullamco.\r\n", + "registered": "2018-05-14T11:00:24 -05:00", + "latitude": -32.893899, + "longitude": -34.464552, + "tags": [ + "adipisicing", + "cillum", + "et", + "fugiat", + "eiusmod", + "irure", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Socorro Nielsen" + }, + { + "id": 1, + "name": "West Ware" + }, + { + "id": 2, + "name": "Graves Carrillo" + } + ], + "greeting": "Hello, Berry Hanson! You have 8 unread messages.", + "favoriteFruit": "banana", + "github": null + }, + { + "_id": "61ed767bda057abbcab39ec3", + "index": 10, + "guid": "5fa5c3e4-c577-40ad-acb9-c734d35545ec", + "isActive": true, + "balance": "$1,071.67", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "blue", + "name": "Vazquez Hansen", + "gender": "male", + "company": "ZYTRAX", + "email": "vazquezhansen@zytrax.com", + "phone": "+1 (864) 586-3257", + "address": "650 Moore Street, Wikieup, Arkansas, 593", + "about": "Cupidatat cupidatat sit aliquip dolor id excepteur. Aliqua do ea sint nisi cupidatat dolor do dolor. Ea do exercitation adipisicing deserunt consectetur anim est nulla sint et magna adipisicing in commodo.\r\n", + "registered": "2018-05-22T04:06:24 -05:00", + "latitude": -57.699413, + "longitude": -100.674608, + "tags": [ + "laborum", + "dolor", + "consectetur", + "esse", + "labore", + "commodo", + "Lorem" + ], + "friends": [ + { + "id": 0, + "name": "Bruce Mckenzie" + }, + { + "id": 1, + "name": "Bobbi Branch" + }, + { + "id": 2, + "name": "Abigail Terrell" + } + ], + "greeting": "Hello, Vazquez Hansen! You have 6 unread messages.", + "favoriteFruit": "strawberry", + "github": "https://github.com/Maura/580" + }, + { + "_id": "61ed767b2acbddb7d4129e03", + "index": 11, + "guid": "580a9347-bf8b-40fc-9b9b-faf14ebf7fc9", + "isActive": false, + "balance": "$2,288.84", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "brown", + "name": "Gaines Robbins", + "gender": "male", + "company": "INJOY", + "email": "gainesrobbins@injoy.com", + "phone": "+1 (879) 487-2743", + "address": "152 Interborough Parkway, Norfolk, Marshall Islands, 812", + "about": "Amet cillum ipsum consectetur officia Lorem deserunt cillum ea aute reprehenderit. Laboris ex officia ut non cupidatat quis ullamco anim dolor dolor. Aliquip enim nostrud adipisicing exercitation sunt nulla aliqua consequat dolor qui. Aliquip officia occaecat deserunt aliquip voluptate aute nulla laborum sit nostrud incididunt tempor.\r\n", + "registered": "2017-07-04T09:10:10 -05:00", + "latitude": -39.101743, + "longitude": 51.140564, + "tags": [ + "laborum", + "sunt", + "cillum", + "duis", + "reprehenderit", + "aute", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Concepcion Wall" + }, + { + "id": 1, + "name": "Waller Barber" + }, + { + "id": 2, + "name": "Carlene Beck" + } + ], + "greeting": "Hello, Gaines Robbins! You have 6 unread messages.", + "favoriteFruit": "strawberry", + "github": null + }, + { + "_id": "61ed767b6a4e2f9393951728", + "index": 12, + "guid": "2253c0dc-9915-4b4f-956f-a924e7928cd2", + "isActive": false, + "balance": "$1,278.09", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Burton Burris", + "gender": "male", + "company": "ECOSYS", + "email": "burtonburris@ecosys.com", + "phone": "+1 (998) 483-2742", + "address": "561 Hill Street, Oretta, Guam, 7831", + "about": "Ipsum aute aliqua ipsum exercitation aute excepteur. In labore quis eiusmod dolore. Aliqua culpa ad reprehenderit ut labore pariatur ex cillum reprehenderit eiusmod velit id duis.\r\n", + "registered": "2014-09-29T04:47:47 -06:00", + "latitude": 32.201188, + "longitude": 75.04406, + "tags": [ + "dolor", + "laborum", + "id", + "aute", + "consectetur", + "nulla", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Josefa Martin" + }, + { + "id": 1, + "name": "Cooke Farrell" + }, + { + "id": 2, + "name": "Oneil Woodard" + } + ], + "greeting": "Hello, Burton Burris! You have 3 unread messages.", + "favoriteFruit": "strawberry", + "github": null + }, + { + "_id": "61ed767bfe3c690139c9921d", + "index": 13, + "guid": "58b48e79-058d-45ef-9737-b81a55f7d043", + "isActive": true, + "balance": "$1,539.78", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "green", + "name": "Torres Murphy", + "gender": "male", + "company": "REMOLD", + "email": "torresmurphy@remold.com", + "phone": "+1 (832) 555-3937", + "address": "238 Wolcott Street, Sterling, Maine, 4339", + "about": "Proident cupidatat aliqua pariatur anim sunt cillum sint est cillum. Ut nulla tempor ea laborum deserunt eiusmod. Ullamco anim proident ad labore ullamco aliquip cupidatat dolore non. Ex do consequat veniam incididunt et ipsum exercitation voluptate. Eu laborum nostrud ullamco irure in amet dolor ad minim ut dolore anim. Cupidatat aliquip quis nostrud Lorem pariatur cupidatat.\r\n", + "registered": "2014-03-09T03:34:56 -06:00", + "latitude": 21.061878, + "longitude": -91.494071, + "tags": [ + "pariatur", + "reprehenderit", + "amet", + "amet", + "incididunt", + "voluptate", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Dorthy Singleton" + }, + { + "id": 1, + "name": "Drake Neal" + }, + { + "id": 2, + "name": "Moore Morales" + } + ], + "greeting": "Hello, Torres Murphy! You have 1 unread messages.", + "favoriteFruit": "strawberry", + "github": "https://github.com/Sondra/232" + }, + { + "_id": "61ed767b32d61ad8073f6a24", + "index": 14, + "guid": "59c34219-f38a-42bb-b9e0-cd6e2e1c6346", + "isActive": true, + "balance": "$1,630.28", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "brown", + "name": "Krista Rogers", + "gender": "female", + "company": "DEVILTOE", + "email": "kristarogers@deviltoe.com", + "phone": "+1 (837) 507-3160", + "address": "756 Narrows Avenue, Juntura, North Carolina, 1695", + "about": "Amet excepteur commodo esse amet commodo minim et magna ea ea labore. Pariatur sint ut fugiat magna sint voluptate. Id nostrud id cupidatat exercitation esse exercitation qui adipisicing deserunt velit veniam fugiat. In laborum esse non sint. Tempor ipsum laborum nisi aute nisi et dolor cillum aliqua proident cillum sunt.\r\n", + "registered": "2015-01-31T02:34:20 -05:00", + "latitude": -43.935432, + "longitude": -70.731948, + "tags": [ + "nisi", + "ullamco", + "id", + "consectetur", + "consequat", + "est", + "mollit" + ], + "friends": [ + { + "id": 0, + "name": "Tonia Gray" + }, + { + "id": 1, + "name": "Leticia House" + }, + { + "id": 2, + "name": "Rosalyn Davenport" + } + ], + "greeting": "Hello, Krista Rogers! You have 4 unread messages.", + "favoriteFruit": "apple", + "github": "https://github.com/Petty/730" + }, + { + "_id": "61ed767baf0e55dca62e7c14", + "index": 15, + "guid": "bf09bc71-95cf-44f8-9d2f-e42c6b1147bb", + "isActive": false, + "balance": "$1,721.80", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "green", + "name": "Golden Downs", + "gender": "male", + "company": "EXERTA", + "email": "goldendowns@exerta.com", + "phone": "+1 (920) 580-3310", + "address": "716 Bushwick Court, Klondike, New Jersey, 6693", + "about": "Veniam culpa eu et irure reprehenderit incididunt enim laborum velit. Nulla anim nulla fugiat magna do aliqua minim ut culpa. Et voluptate cillum culpa dolore pariatur laborum amet sunt do adipisicing esse ipsum. Aliqua qui amet Lorem culpa nostrud velit voluptate consectetur fugiat non sit voluptate. Id deserunt magna laboris consequat labore. Ullamco consequat esse duis mollit pariatur quis id consectetur pariatur sint consequat.\r\n", + "registered": "2021-05-04T02:58:01 -05:00", + "latitude": 86.626409, + "longitude": -10.241644, + "tags": [ + "aliqua", + "aute", + "reprehenderit", + "nisi", + "enim", + "amet", + "fugiat" + ], + "friends": [ + { + "id": 0, + "name": "Madden Wilkins" + }, + { + "id": 1, + "name": "Gail Mcintosh" + }, + { + "id": 2, + "name": "Rosalind Booker" + } + ], + "greeting": "Hello, Golden Downs! You have 1 unread messages.", + "favoriteFruit": "banana", + "github": null + }, + { + "_id": "61ed767b8de52761544a3abc", + "index": 16, + "guid": "a7bb8af0-c830-4bcc-9945-ab1094cdc32d", + "isActive": false, + "balance": "$1,125.75", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Kimberley Kemp", + "gender": "female", + "company": "BIOLIVE", + "email": "kimberleykemp@biolive.com", + "phone": "+1 (963) 593-2249", + "address": "638 Arlington Avenue, Trona, West Virginia, 5254", + "about": "Excepteur ea elit duis magna proident. Veniam adipisicing ipsum qui consequat officia pariatur ex. Lorem in aute dolor dolor cupidatat officia culpa aliquip mollit ullamco deserunt ullamco enim eu.\r\n", + "registered": "2016-12-12T08:28:42 -05:00", + "latitude": 72.460646, + "longitude": 43.854724, + "tags": [ + "non", + "dolore", + "incididunt", + "irure", + "nostrud", + "deserunt", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Mclaughlin Cobb" + }, + { + "id": 1, + "name": "Fitzgerald Rasmussen" + }, + { + "id": 2, + "name": "Horne Langley" + } + ], + "greeting": "Hello, Kimberley Kemp! You have 3 unread messages.", + "favoriteFruit": "strawberry", + "github": null + }, + { + "_id": "61ed767bf4e31140817e5ac7", + "index": 17, + "guid": "006cf374-c5a9-4c9c-9319-5a79867bf63b", + "isActive": false, + "balance": "$2,853.28", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "brown", + "name": "Meagan Mcknight", + "gender": "female", + "company": "AMRIL", + "email": "meaganmcknight@amril.com", + "phone": "+1 (927) 501-2641", + "address": "748 Oceanview Avenue, Nutrioso, Wisconsin, 1159", + "about": "Mollit in nostrud amet est. Exercitation amet elit cupidatat quis Lorem veniam officia nostrud. Enim veniam ea sint nisi amet elit eu tempor. Occaecat quis elit exercitation duis magna voluptate.\r\n", + "registered": "2015-05-02T12:55:48 -05:00", + "latitude": 80.669585, + "longitude": 56.094324, + "tags": [ + "duis", + "nulla", + "commodo", + "qui", + "pariatur", + "laborum", + "exercitation" + ], + "friends": [ + { + "id": 0, + "name": "Mcneil Livingston" + }, + { + "id": 1, + "name": "Sosa Mccarty" + }, + { + "id": 2, + "name": "Levine Sexton" + } + ], + "greeting": "Hello, Meagan Mcknight! You have 7 unread messages.", + "favoriteFruit": "banana", + "github": null + }, + { + "_id": "61ed767b9528f2546bd0138a", + "index": 18, + "guid": "978ec8c7-3321-49b3-86ef-2648f8e328db", + "isActive": true, + "balance": "$2,370.65", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "brown", + "name": "Phillips Green", + "gender": "male", + "company": "TROPOLI", + "email": "phillipsgreen@tropoli.com", + "phone": "+1 (862) 412-3867", + "address": "346 Dearborn Court, Loyalhanna, Utah, 8400", + "about": "Lorem mollit elit officia exercitation laboris eiusmod ex in aute Lorem tempor. Esse et deserunt cillum dolor eu. Esse in exercitation incididunt ad irure qui irure culpa fugiat. Ad aliquip id cillum adipisicing velit consectetur ut non et magna non dolore sit. Ullamco commodo irure non excepteur ipsum reprehenderit aliqua.\r\n", + "registered": "2021-03-22T03:35:38 -05:00", + "latitude": 42.876942, + "longitude": -55.499282, + "tags": [ + "nostrud", + "laboris", + "laborum", + "est", + "amet", + "amet", + "laboris" + ], + "friends": [ + { + "id": 0, + "name": "Antonia Fuller" + }, + { + "id": 1, + "name": "Jerry Blackwell" + }, + { + "id": 2, + "name": "Olsen Hickman" + } + ], + "greeting": "Hello, Phillips Green! You have 1 unread messages.", + "favoriteFruit": "apple", + "github": null + }, + { + "_id": "61ed767bf49fa6339e8a22f8", + "index": 19, + "guid": "7f05839e-ceab-4d62-9c82-14f6d0b0dc43", + "isActive": true, + "balance": "$1,396.73", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Marion Leon", + "gender": "female", + "company": "VIASIA", + "email": "marionleon@viasia.com", + "phone": "+1 (883) 479-2471", + "address": "138 Utica Avenue, Boykin, North Dakota, 8839", + "about": "Eiusmod in dolore aliquip nostrud. Eu consectetur laboris sit aliquip duis. Occaecat ea minim dolore deserunt commodo ex. Labore eiusmod laborum qui magna laboris eiusmod consectetur cillum culpa nostrud pariatur deserunt minim dolor. Esse elit cillum ad in Lorem ex duis duis laborum est deserunt.\r\n", + "registered": "2015-05-24T02:56:27 -05:00", + "latitude": 39.479427, + "longitude": -15.294262, + "tags": [ + "incididunt", + "minim", + "reprehenderit", + "ad", + "reprehenderit", + "do", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Douglas Randolph" + }, + { + "id": 1, + "name": "Camacho Knox" + }, + { + "id": 2, + "name": "Day Hampton" + } + ], + "greeting": "Hello, Marion Leon! You have 1 unread messages.", + "favoriteFruit": "strawberry", + "github": "https://github.com/Ines/788" + } +] +` diff --git a/benchmarks/src/json/ast.ts b/benchmarks/src/json/ast.ts new file mode 100644 index 0000000..3e1a1c8 --- /dev/null +++ b/benchmarks/src/json/ast.ts @@ -0,0 +1,38 @@ +export interface JsonObject { + type: 'object' + values: Array +} + +export interface JsonObjectProp { + type: 'property' + name: string + value: JsonValue +} + +export interface JsonArray { + type: 'array' + values: Array +} + +export interface JsonString { + type: 'string' + value: string +} + +export interface JsonNumber { + type: 'number' + value: number +} + +export interface JsonBoolean { + type: 'boolean' + value: boolean +} + +export interface JsonNull { + type: 'null' + value: null +} + +export type JsonValue = JsonObject | JsonArray | JsonString | JsonNumber | JsonBoolean | JsonNull +export type JsonRoot = JsonObject | JsonArray diff --git a/benchmarks/src/json/index.ts b/benchmarks/src/json/index.ts new file mode 100644 index 0000000..6fdd37e --- /dev/null +++ b/benchmarks/src/json/index.ts @@ -0,0 +1,20 @@ +import { suite, add, cycle, complete } from 'benny' + +import { parse as parseSigma } from './sigma' +import { parse as parseParjs } from './parjs' + +import { SAMPLE } from './@sample' + +const options = { + minSamples: 50 +} + +suite( + 'JSON :: sigma vs parjs', + + add('sigma', () => parseSigma(SAMPLE), options), + add('parjs', () => parseParjs(SAMPLE), options), + + cycle(), + complete() +) diff --git a/benchmarks/src/json/parjs.ts b/benchmarks/src/json/parjs.ts new file mode 100644 index 0000000..666cdac --- /dev/null +++ b/benchmarks/src/json/parjs.ts @@ -0,0 +1,179 @@ +import { anyStringOf, float, string, stringLen, anyCharOf, noCharOf, whitespace } from 'parjs' +import { + later, + many, + manySepBy, + map, + or, + stringify, + qthen, + thenq, + then, + between +} from 'parjs/combinators' + +import * as Ast from './ast' + +/* Tokens. */ + +const Keywords = { + True: 'true', + False: 'false', + Null: 'null' +} as const + +const Terminals = { + OpenBrace: '{', + CloseBrace: '}', + OpenSquare: '[', + CloseSquare: ']', + Colon: ':', + Comma: ',', + Quote: '"' +} as const + +const Escapes: Record = { + '"': `"`, + '\\': '\\', + '/': '/', + f: '\f', + n: '\n', + r: '\r', + t: '\t' +} + +/* Mapping functions to turn parsed string values into AST nodes. */ + +function toObject(values: Array): Ast.JsonObject { + return { + type: 'object', + values + } +} + +function toObjectProp(tuple: [Ast.JsonString, Ast.JsonValue]): Ast.JsonObjectProp { + const [{ value: name }, value] = tuple + + return { + type: 'property', + name, + value + } +} + +function toArray(values: Array): Ast.JsonArray { + return { + type: 'array', + values + } +} + +function toString(value: string): Ast.JsonString { + return { + type: 'string', + value + } +} + +function toNumber(value: number): Ast.JsonNumber { + return { + type: 'number', + value + } +} + +function toBoolean(kind: string): Ast.JsonBoolean { + switch (kind) { + case Keywords.True: { + return { + type: 'boolean', + value: true + } + } + + case Keywords.False: { + return { + type: 'boolean', + value: false + } + } + + default: { + return { + type: 'boolean', + value: false + } + } + } +} + +function toNull(): Ast.JsonNull { + return { + type: 'null', + value: null + } +} + +/* Parsers. */ + +const pJsonValue = later() +const pJsonRoot = later() + +const pEscapeChar = anyCharOf(Object.keys(Escapes).join()).pipe(map((char) => Escapes[char])) + +const pEscapeUnicode = string('u').pipe( + qthen( + stringLen(4).pipe( + map((str) => parseInt(str, 16)), + map((x) => String.fromCharCode(x)) + ) + ) +) + +const pEscapeAny = string('\\').pipe(qthen(pEscapeChar.pipe(or(pEscapeUnicode)))) +const pCharOrEscape = pEscapeAny.pipe(or(noCharOf(Terminals.Quote))) +const pString = pCharOrEscape.pipe(many(), stringify(), between(Terminals.Quote)) +const pJsonString = pString.pipe(map(toString)) +const pBool = anyStringOf(Keywords.True, Keywords.False).pipe(map(toBoolean)) +const pNull = string(Keywords.Null).pipe(map(toNull)) +const pNumber = float().pipe(map(toNumber)) + +const pArray = pJsonValue.pipe( + manySepBy(Terminals.Comma), + between(Terminals.OpenSquare, Terminals.CloseSquare), + map(toArray) +) + +const pObjectProperty = pString.pipe( + thenq(string(Terminals.Colon).pipe(between(whitespace()))), + then(pJsonValue), + between(whitespace()), + map(([name, value]) => toObjectProp([toString(name), value])) +) + +const pObject = pObjectProperty.pipe( + manySepBy(Terminals.Comma), + between(Terminals.OpenBrace, Terminals.CloseBrace), + map(toObject) +) + +pJsonValue.init( + pJsonString.pipe(or(pNull, pNumber, pBool), or(pArray, pObject), between(whitespace())) +) + +pJsonRoot.init(pArray.pipe(or(pObject), between(whitespace()))) + +/* Wrapper for bench runner. */ + +export function parse(text: string): Ast.JsonRoot { + const result = pJsonRoot.parse(text) + + if (result.kind === 'OK') { + return result.value + } + + return { + type: 'object', + values: [] + } +} diff --git a/benchmarks/src/json/sigma.ts b/benchmarks/src/json/sigma.ts new file mode 100644 index 0000000..7c7f8a1 --- /dev/null +++ b/benchmarks/src/json/sigma.ts @@ -0,0 +1,170 @@ +import { choice, sepBy, map, takeMid, optional, sequence } from '@nrsk/sigma/combinators' +import { defer, float, int, regexp, run, string, whitespace } from '@nrsk/sigma/parsers' + +import * as Ast from './ast' + +/* Tokens. */ + +const Keywords = { + True: 'true', + False: 'false', + Null: 'null' +} as const + +const Terminals = { + OpenBrace: '{', + CloseBrace: '}', + OpenSquare: '[', + CloseSquare: ']', + Colon: ':', + Comma: ',' +} as const + +/* Mapping functions to turn parsed string values into AST nodes. */ + +function toObject(values: Array): Ast.JsonObject { + return { + type: 'object', + values + } +} + +function toObjectProp(tuple: [Ast.JsonString, string, Ast.JsonValue]): Ast.JsonObjectProp { + const [{ value: name }, _, value] = tuple + + return { + type: 'property', + name, + value + } +} + +function toArray(values: Array): Ast.JsonArray { + return { + type: 'array', + values + } +} + +function toString(text: string): Ast.JsonString { + return { + type: 'string', + value: text.slice(1, -1) + } +} + +function toNumber(value: number): Ast.JsonNumber { + return { + type: 'number', + value: value + } +} + +function toBoolean(kind: string): Ast.JsonBoolean { + switch (kind) { + case Keywords.True: { + return { + type: 'boolean', + value: true + } + } + + case Keywords.False: { + return { + type: 'boolean', + value: false + } + } + + default: { + return { + type: 'boolean', + value: false + } + } + } +} + +function toNull(): Ast.JsonNull { + return { + type: 'null', + value: null + } +} + +/* Parsers. */ + +// Non-Terminals. +const NumberLiteral = choice(float(), int()) + +const Space = optional(whitespace()) +const StringLiteral = regexp(/"([^"]|\\.)*"/g, 'string') + +// Utility. +const match = (match: string) => takeMid(Space, string(match), Space) + +// Composites. +const JsonRoot = defer() +const JsonObject = defer() +const JsonObjectProp = defer() +const JsonArray = defer() +const JsonString = defer() +const JsonNumber = defer() +const JsonBoolean = defer() +const JsonNull = defer() +const JsonValue = defer() + +JsonRoot.with(choice(JsonObject, JsonArray)) + +JsonObject.with( + map( + takeMid( + match(Terminals.OpenBrace), + sepBy(JsonObjectProp, match(Terminals.Comma)), + match(Terminals.CloseBrace) + ), + toObject + ) +) + +JsonObjectProp.with(map(sequence(JsonString, match(Terminals.Colon), JsonValue), toObjectProp)) + +JsonArray.with( + map( + takeMid( + match(Terminals.OpenSquare), + sepBy(JsonValue, match(Terminals.Comma)), + match(Terminals.CloseSquare) + ), + toArray + ) +) + +JsonNull.with(map(match(Keywords.Null), toNull)) + +JsonString.with(map(StringLiteral, toString)) + +JsonNumber.with(map(NumberLiteral, toNumber)) + +JsonBoolean.with(map(choice(match(Keywords.True), match(Keywords.False)), toBoolean)) + +JsonValue.with(choice(JsonObject, JsonArray, JsonString, JsonNumber, JsonBoolean, JsonNull)) + +/* Wrapper for bench runner. */ + +export function parse(text: string): Ast.JsonRoot { + const result = run(JsonRoot).with(text) + + switch (result.kind) { + case 'success': { + return result.value + } + + case 'failure': { + return { + type: 'object', + values: [] + } + } + } +} diff --git a/benchmarks/src/tuple/@sample.ts b/benchmarks/src/tuple/@sample.ts new file mode 100644 index 0000000..50f2f20 --- /dev/null +++ b/benchmarks/src/tuple/@sample.ts @@ -0,0 +1 @@ +export const SAMPLE = `(1, 2, (3, 4, (5, 6, 7, (8), (9, 10, (11, 12, 13)), 14), 15))` diff --git a/benchmarks/src/tuple/ast.ts b/benchmarks/src/tuple/ast.ts new file mode 100644 index 0000000..e726d29 --- /dev/null +++ b/benchmarks/src/tuple/ast.ts @@ -0,0 +1,9 @@ +export interface NumberNode { + type: 'number' + value: number +} + +export interface ListNode { + type: 'list' + value: Array +} diff --git a/benchmarks/src/tuple/index.ts b/benchmarks/src/tuple/index.ts new file mode 100644 index 0000000..3a98aff --- /dev/null +++ b/benchmarks/src/tuple/index.ts @@ -0,0 +1,20 @@ +import { suite, add, cycle, complete } from 'benny' + +import { parse as parseSigma } from './sigma' +import { parse as parseParjs } from './parjs' + +import { SAMPLE } from './@sample' + +const options = { + minSamples: 50 +} + +suite( + 'Tuple :: sigma vs parjs', + + add('sigma', () => parseSigma(SAMPLE), options), + add('parjs', () => parseParjs(SAMPLE), options), + + cycle(), + complete() +) diff --git a/benchmarks/src/tuple/parjs.ts b/benchmarks/src/tuple/parjs.ts new file mode 100644 index 0000000..b1dfbad --- /dev/null +++ b/benchmarks/src/tuple/parjs.ts @@ -0,0 +1,50 @@ +import { between, later, manySepBy, map, or } from 'parjs/combinators' +import { int, string, whitespace } from 'parjs' + +import * as Ast from './ast' + +/* Mapping functions to turn parsed string values into AST nodes. */ + +function toNumber(value: number): Ast.NumberNode { + return { + type: 'number', + value + } +} + +function toList(value: Array): Ast.ListNode { + return { + type: 'list', + value + } +} + +/* Parsers. */ + +const OpenParen = string('(') +const CloseParen = string(')') +const Comma = string(',').pipe(between(whitespace())) + +const TupleNumber = later() +const TupleList = later() + +TupleNumber.init(int().pipe(map(toNumber))) + +TupleList.init( + TupleNumber.pipe(or(TupleList), manySepBy(Comma), between(OpenParen, CloseParen), map(toList)) +) + +/* Wrapper for bench runner. */ + +export function parse(text: string): Ast.ListNode { + const result = TupleList.parse(text) + + if (result.kind === 'OK') { + return result.value + } + + return { + type: 'list', + value: [] + } +} diff --git a/benchmarks/src/tuple/sigma.ts b/benchmarks/src/tuple/sigma.ts new file mode 100644 index 0000000..00adcb8 --- /dev/null +++ b/benchmarks/src/tuple/sigma.ts @@ -0,0 +1,64 @@ +import { choice, map, optional, sepBy, sequence, takeMid } from '@nrsk/sigma/combinators' +import { defer, regexp, run, string, whitespace } from '@nrsk/sigma/parsers' + +import * as Ast from './ast' + +/* Tokens. */ + +const Terminals = { + OpenParen: '(', + CloseParen: ')', + Comma: ',' +} as const + +/* Mapping functions to turn parsed string values into AST nodes. */ + +function toNumber(value: string): Ast.NumberNode { + return { + type: 'number', + value: +value + } +} + +function toList(value: Array): Ast.ListNode { + return { + type: 'list', + value + } +} + +/* Parsers. */ + +const OpenParen = string(Terminals.OpenParen) +const CloseParen = string(Terminals.CloseParen) +const Space = optional(whitespace()) +const Comma = sequence(Space, string(Terminals.Comma), Space) +const Integer = regexp(/-?\d+/g, 'signed integer') + +const TupleNumber = defer() +const TupleList = defer() + +TupleNumber.with(map(Integer, toNumber)) + +TupleList.with( + map(takeMid(OpenParen, sepBy(choice(TupleList, TupleNumber), Comma), CloseParen), toList) +) + +/* Wrapper for bench runner. */ + +export function parse(text: string): Ast.ListNode { + const result = run(TupleList).with(text) + + switch (result.kind) { + case 'success': { + return result.value + } + + case 'failure': { + return { + type: 'list', + value: [] + } + } + } +} diff --git a/benchmarks/tsconfig.json b/benchmarks/tsconfig.json new file mode 100644 index 0000000..1ebecf5 --- /dev/null +++ b/benchmarks/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "target": "es2021", + "outDir": "./dist", + "incremental": true, + "declaration": false + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json index 807b7ef..a7e3cf2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,5 +15,5 @@ "@tests/*": ["tests/*"] } }, - "include": ["scripts", "src", "tests"] + "include": ["benchmarks", "scripts", "src", "tests"] }