diff --git a/package.json b/package.json index 259c2697e..a4f408673 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@oclif/plugin-plugins": "^2.4.7", "@oclif/test": "^2.3.15", "@types/ansi-styles": "^3.2.1", + "@types/benchmark": "^2.1.2", "@types/chai": "^4.3.4", "@types/chai-as-promised": "^7.1.5", "@types/clean-stack": "^2.1.1", @@ -59,6 +60,7 @@ "@types/supports-color": "^8.1.1", "@types/wordwrap": "^1.0.1", "@types/wrap-ansi": "^3.0.0", + "benchmark": "^2.1.4", "chai": "^4.3.7", "chai-as-promised": "^7.1.1", "commitlint": "^12.1.4", @@ -111,7 +113,8 @@ "prepack": "yarn run build", "test": "mocha --forbid-only \"test/**/*.test.ts\"", "test:e2e": "mocha --forbid-only \"test/**/*.e2e.ts\" --timeout 1200000", - "pretest": "yarn build --noEmit && tsc -p test --noEmit --skipLibCheck" + "pretest": "yarn build --noEmit && tsc -p test --noEmit --skipLibCheck", + "test:perf": "ts-node test/perf/parser.perf.ts" }, "types": "lib/index.d.ts" -} \ No newline at end of file +} diff --git a/perf.txt b/perf.txt new file mode 100644 index 000000000..b6928c781 --- /dev/null +++ b/perf.txt @@ -0,0 +1,6 @@ +yarn run v1.22.19 +$ ts-node test/perf/parser.perf.ts +simple x 103,392 ops/sec ±0.91% (77 runs sampled) +multiple async flags that take time x 4.96 ops/sec ±0.13% (28 runs sampled) +multiple async flags that take time x 5,451 ops/sec ±2.09% (79 runs sampled) +Done in 21.11s. diff --git a/test/perf/parser.perf.ts b/test/perf/parser.perf.ts new file mode 100644 index 000000000..da529f3c1 --- /dev/null +++ b/test/perf/parser.perf.ts @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import {Suite} from 'benchmark' +import {parse} from '../../src/parser' +import {Flags} from '../../src' + +const suite = new Suite() + +// eslint-disable-next-line no-promise-executor-return +const delay100 = () => new Promise(resolve => setTimeout(resolve, 100)) + +suite +.add('simple', + { + defer: true, + fn: function (deferred: { resolve: () => any }) { + parse(['--bool'], { + flags: { + bool: Flags.boolean(), + }, + }).then(() => deferred.resolve()) + }, + }) +.add('multiple async flags that take time', { + defer: true, + fn: function (deferred: { resolve: () => any }) { + parse(['--flagA', 'foo', '--flagA', 'bar'], { + flags: { + flagA: Flags.string({ + parse: async input => { + await delay100() + return input + }, + }), + flagB: Flags.string({ + parse: async input => { + await delay100() + return input + }, + }), + }, + }).then(() => deferred.resolve()) + }, +}) + +.add('flagstravaganza', { + defer: true, + fn: function (deferred: { resolve: () => any }) { + const flags = [ + ['--bool'], + ['-S', 'foo'], + + ['--dep-string', 'foo'], + ['--excl-string', 'foo'], + ['--exactly-one', 'foo'], + + ['--parsed-string-as-number', '5'], + ['--dir', process.cwd()], + ['--file', __filename], + + ['--multiple', '1'], + ['--multiple', '2'], + ['--multiple', '3'], + ['--multiple2', '5,6,7,8,9,10,11'], + ] + const exactlyOne = ['exactly-one-nope', 'exactly-one-nope2', 'exactly-one'] + parse(flags.flat(), { + flags: { + bool: Flags.boolean(), + string: Flags.string({char: 's', aliases: ['S']}), + + 'dep-string': Flags.string({dependsOn: ['string']}), + // don't populate this one, used for exclusive test + nope: Flags.boolean(), + 'excl-string': Flags.string({exclusive: ['nope']}), + 'exactly-one-nope': Flags.string({exactlyOne}), + 'exactly-one-nope2': Flags.string({exactlyOne}), + 'exactly-one': Flags.string({exactlyOne}), + + 'parsed-string-as-number': Flags.integer({parse: input => Promise.resolve(Number.parseInt(input, 10) + 1000)}), + dir: Flags.directory({exists: true}), + file: Flags.file({exists: true}), + + multiple: Flags.string({multiple: true}), + multiple2: Flags.string({multiple: true, delimiter: ','}), + }, + }).then(() => deferred.resolve()) + }, +}) + +// add listeners +.on('cycle', (event: any) => { + console.log(String(event.target)) +}) +.run({async: true}) diff --git a/yarn.lock b/yarn.lock index 3cdead2f3..7d74195ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -567,6 +567,11 @@ dependencies: "@types/color-name" "*" +"@types/benchmark@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/benchmark/-/benchmark-2.1.2.tgz#b7838408c93dc08ceb4e6e13147dbfbe6a151f82" + integrity sha512-EDKtLYNMKrig22jEvhXq8TBFyFgVNSPmDF2b9UzJ7+eylPqdZVo17PCUMkn1jP6/1A/0u78VqYC6VrX6b8pDWA== + "@types/chai-as-promised@^7.1.5": version "7.1.5" resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" @@ -982,6 +987,14 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +benchmark@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" + integrity sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ== + dependencies: + lodash "^4.17.4" + platform "^1.3.3" + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -2300,7 +2313,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= -lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2709,6 +2722,11 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +platform@^1.3.3: + version "1.3.6" + resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" + integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== + plur@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84"