Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: replace subcommands with arguments #36

Merged
merged 16 commits into from
Dec 20, 2023

Conversation

xDivisionByZerox
Copy link
Member

Description

This PR significantly reduces the runtime duration of the CLI. This is achieved by using a single CLI argument instead of subcommands. While subcommands might be nicer for user experience, they are quite slow in execution. The next section contains some numbers on performance improvements.

Performance Numbers

Name Fastest (ms) Slowest (ms) Average (ms)
Subcommands (old) 3112.690999999875 3728.2561999999452 3177.6487029999935
Argument (new) 369.8300000000745 561.94020000007 393.3905530000105

*100 iterations per implementation

This equates to the following performance increases:

  • ~88,12% for the fastest run
  • ~84,93% for the slowest run
  • ~87,62% for the average run
All Iterations
Number Subcommands Times (ms) Argument Time(ms)
1 3319.684899999993 384.1920000007376
2 3136.651700000046 536.2269000001252
3 3132.0475000001024 507.1458000000566
4 3166.9779000000563 557.4335000002757
5 3328.5652999999 392.76790000032634
6 3164.278900000034 384.62159999925643
7 3154.3236000000034 406.69419999979436
8 3158.9210999999195 395.39620000030845
9 3266.8633999999147 418.8018999993801
10 3162.659999999916 561.94020000007
11 3135.1700999999885 374.06819999963045
12 3155.624700000044 390.1156000001356
13 3144.8545999999624 375.0890000006184
14 3160.3072000001557 389.99859999958426
15 3133.649999999907 373.3689000001177
16 3123.1928999999072 377.6628000000492
17 3130.691499999957 399.228900000453
18 3146.312000000151 373.3975999997929
19 3142.03469999996 378.39840000029653
20 3199.216500000097 379.8678999999538
21 3172.6451000000816 376.88100000005215
22 3171.9170999999624 392.5893999999389
23 3159.4300999999978 378.57299999985844
24 3284.6784000000916 376.29580000042915
25 3149.022999999812 395.7428999999538
26 3139.5492000000086 377.7733000004664
27 3146.351400000043 395.2636000001803
28 3131.847300000023 378.08660000003874
29 3153.3229000000283 378.6003999998793
30 3164.676499999827 395.23460000008345
31 3140.0716999999713 398.6864999998361
32 3139.8561999998055 451.841599999927
33 3134.623499999987 398.9718000004068
34 3151.432599999942 377.4216999998316
35 3169.8572999997996 388.7110999999568
36 3164.5841999999247 373.9029000001028
37 3160.7571999998763 382.511999999173
38 3155.5520000001416 378.63350000046194
39 3169.9786000000313 376.88320000004023
40 3186.7923999999184 418.31759999971837
41 3120.1448999999557 369.8300000000745
42 3122.8907999999356 374.70770000014454
43 3294.244799999986 405.821600000374
44 3143.0840000000317 379.4485999997705
45 3131.991299999878 386.5625
46 3138.6099000000395 377.2380999997258
47 3140.8340000000317 379.5548000000417
48 3134.152100000065 397.32789999991655
49 3161.0210000001825 373.2384000001475
50 3143.877199999988 373.3730999995023
51 3164.5512000001036 381.91369999945164
52 3162.208699999843 376.6074999999255
53 3167.65419999999 393.5575999999419
54 3160.3560999999754 372.0955999996513
55 3149.9816999998875 381.571600000374
56 3190.6091000000015 398.5948999999091
57 3164.3843000000343 383.97750000003725
58 3224.4292000001296 380.25339999981225
59 3229.535600000061 384.98620000015944
60 3159.5550999999978 375.25499999988824
61 3185.282200000016 396.1024000002071
62 3312.6783000000287 381.28830000013113
63 3180.818600000115 379.66079999972135
64 3182.6322999999393 389.0388000002131
65 3188.8554999998305 381.6946000000462
66 3262.7369000001345 395.9600999997929
67 3192.149499999825 372.3124000001699
68 3154.6720000000205 374.9057999998331
69 3169.3649999999907 399.0997000001371
70 3137.097800000105 408.81529999990016
71 3145.0470000000205 374.03120000008494
72 3130.464600000065 375.5116000007838
73 3120.865899999859 415.57070000004023
74 3125.2304000000004 403.5201000003144
75 3137.624199999962 375.2059000004083
76 3212.535399999935 442.65820000041276
77 3293.8044000000227 408.0756999999285
78 3158.882200000109 408.56460000015795
79 3157.0719000000972 398.1101000001654
80 3255.599099999992 378.8293000003323
81 3237.5068999999203 381.96689999941736
82 3162.126900000032 380.12189999967813
83 3144.782499999972 380.96750000026077
84 3154.787699999986 391.0795999998227
85 3194.7552999998443 374.4811000004411
86 3162.7360999998637 375.86080000083894
87 3151.0804999999236 396.6379999993369
88 3152.5785999998916 379.5120000001043
89 3183.125199999893 385.2373999999836
90 3156.6108000001404 382.6787000000477
91 3134.602200000081 380.48599999956787
92 3728.2561999999452 394.3316000001505
93 3221.1473000000697 378.70589999947697
94 3190.654300000053 381.15889999922365
95 3241.190100000007 392.84860000014305
96 3181.5431999999564 380.37289999984205
97 3127.8911000001244 393.1602999996394
98 3112.690999999875 378.83460000064224
99 3275.5373000002 376.03940000012517
100 3134.7635000001173 402.3632999993861

System Info:

OS: Windows 10 10.0.19045
CPU: (4) x64 Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz
Memory: 8.74 GB / 15.91 GB

@xDivisionByZerox xDivisionByZerox added the c: refactor PR that affects the runtime behavior, but doesn't add new features or fixes bugs label Dec 18, 2023
@xDivisionByZerox xDivisionByZerox self-assigned this Dec 18, 2023
@xDivisionByZerox
Copy link
Member Author

xDivisionByZerox commented Dec 18, 2023

This implementation might be insufficient if Faker decides to implement functions with the same name (currently for example faker.datatype.hexadecimal and faker.string.hexadecimal). In the future I'll provide an optional module option that allows to explicitly set the module the function should be from:

npx faker -m string hexadecimal
> 0xC

npx faker --module string hexadecimal
> 0xF

It is also noteworthy that the function name currently is matched case sensitive. This behavior might change as well in the future if it turns out to be bad DX.

Copy link
Member

@ST-DDT ST-DDT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future descriptions please include a execution diff.
e.g.

// Old
faker [options] module_name entry_name
// New
faker int ....

I see why you want to omit the sub commands.
But where is the actual implementation of the sub commands/ calls of the faker invocation?

Instead of using faker int we could also use faker number.int that way we have the module name directly in the command and don't have to randomly search the method, but we can instead directly refer to/resolve it. (I hope this translates well in v9 to an import e.g. import fn from @faker-js/faker/modules/number/int)

README.md Outdated Show resolved Hide resolved
@xDivisionByZerox
Copy link
Member Author

For future descriptions please include a execution diff.

I hope that I wouln't have to change the interface to often. But can do if it should happen again.

But where is the actual implementation of the sub commands/ calls of the faker invocation?

Its here:

console.log(fn());

fn is the actual entry in the faker instance.

Instead of using faker int we could also use faker number.int that way we have the module name directly in the command and don't have to randomly search the method, but we can instead directly refer to/resolve it. (I hope this translates well in v9 to an import e.g. import fn from @faker-js/faker/modules/number/int)

Yeah, I'm more looking forward to a tree-shakeable Faker that exprot all it's functions separatly. Thats why I decided to implement it with a single name argument. Additionally, I would not say that the format of number.int is a standard argument format. I could however think about extending the "functionName" argument to support those cases. Nevertheless, I don't see this syntax in an MVP.

xDivisionByZerox and others added 2 commits December 18, 2023 22:36
Co-authored-by: ST-DDT <ST-DDT@gmx.de>
src/index.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
@ST-DDT
Copy link
Member

ST-DDT commented Dec 18, 2023

But where is the actual implementation of the sub commands/ calls of the faker invocation?

Its here:

console.log(fn());

I thought there was already a way to provide parameters, but I'm mistaken.

@ST-DDT
Copy link
Member

ST-DDT commented Dec 18, 2023

Additionally, I would not say that the format of number.int is a standard argument format. I could however think about extending the "functionName" argument to support those cases.

My concern is that just functionName might not be stable, because due to packaging or whatever magic (minification/variable aliasing), the modules could be in different order and thus faker.datatype.hexadecimal and faker.string.hexadecimal (animal/database.type, hacker/word.verb, ...) might swap places in minor version upgrades. Also just the function name cannot make use of any future tree shaking capabilities.

Also if the dot notation is the main issue, isn't it possible to just add another argument like this:

.argument(
      '<module>',
      'The name of the module to invoke.',
    )
.argument(
      '<function>',
      'The name of the function to invoke.',
    )
.action(async (moduleName, functionName) => { ... })

@xDivisionByZerox
Copy link
Member Author

Also if the dot notation is the main issue, isn't it possible to just add another argument like this:

.argument(
      '<module>',
      'The name of the module to invoke.',
    )
.argument(
      '<function>',
      'The name of the function to invoke.',
    )
.action(async (moduleName, functionName) => { ... })

I liked that idea. So simple, that I didn't even consider it. Thank you for the suggestion 👍

@xDivisionByZerox xDivisionByZerox changed the title refactor: replace subcommands with single argument refactor: replace subcommands with arguments Dec 19, 2023
ST-DDT
ST-DDT previously approved these changes Dec 19, 2023
README.md Show resolved Hide resolved
src/errors/argument.error.ts Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
ST-DDT
ST-DDT previously approved these changes Dec 19, 2023
README.md Outdated Show resolved Hide resolved
@xDivisionByZerox xDivisionByZerox merged commit 4bd2f5d into main Dec 20, 2023
4 checks passed
@xDivisionByZerox xDivisionByZerox deleted the refactor/replace-subcommands-with-argument branch December 20, 2023 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: refactor PR that affects the runtime behavior, but doesn't add new features or fixes bugs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants