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

fix: improve addChild and path performance #1891

Merged
merged 3 commits into from
Aug 29, 2023
Merged

fix: improve addChild and path performance #1891

merged 3 commits into from
Aug 29, 2023

Conversation

Chriscbr
Copy link
Contributor

@Chriscbr Chriscbr commented Aug 27, 2023

Improve the performance of the constructs library by removing several branches in the library's hot paths and switching to some more performant operations.

On my laptop, the benchmark I used (shared in a gist here) takes about 5.0-5.3 seconds with the old version of constructs, and about 1.1-1.2 seconds with the new version of constructs.

Misc:

  • Removed an unused file in the test folder.
  • Added some files to npmignore to reduce the package's npm footprint.

@@ -77,7 +77,12 @@ export class Node {
* Components are separated by '/'.
*/
public get path(): string {
const components = this.scopes.filter(c => c.node.id).map(c => c.node.id);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Calling filter generates one array, and calling map after creates another array. It should be slightly faster to create a single array and perform filtering inside a for loop.

@@ -417,21 +422,13 @@ export class Node {
throw new Error(`Cannot add children to "${this.path}" during synthesis`);
}

if (childName in this._children) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I tested, array access is slightly faster than using the "in" operator

Comment on lines -426 to -428
if (!childName && this.id) {
throw new Error(`cannot add a nameless construct to the named scope: ${this.path}`);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think this if branch can get called. Here's my reasoning:

  1. addChild is only called if a non-null scope is passed to the Node constructor.
  2. if a non-null scope is passed to the Node constructor, and this.id has a falsey value (like undefined or an empty string), then an error will be thrown in the Node constructor before addChild is called.
  3. based on (1) and (2), when addChild is called, it's guaranteed that childName will not be a falsey value
  4. the if statement's body only executes if childName takes on a falsey value

I tried coming up with a test case that would actually throw this error but I don't think there's a way.

Comment on lines -432 to -434
if (Object.keys(this._children).length > 1 && Object.keys(this._children).filter(x => !x).length > 0) {
throw new Error('only a single construct is allowed in a scope if it has an empty name');
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also don't think this branch can ever get called. Here was my reasoning:

  1. From my other comment, childName will never take on a falsey value (like an empty string).
  2. From (1), the line this._children[childName] = childl can never add falsey values as keys to this._children.
  3. There are no other lines of code that add new keys to this._children.
  4. Therefore, this._children will always have keys with truthy values, so Object.keys(this._children).filter(x => !x) can never have a length greater than 0.

@mrgrain
Copy link
Contributor

mrgrain commented Aug 29, 2023

image

Copy link
Contributor

@mrgrain mrgrain left a comment

Choose a reason for hiding this comment

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

Ha thanks for that!

@mergify mergify bot merged commit fdde3da into aws:10.x Aug 29, 2023
13 checks passed
@Chriscbr Chriscbr deleted the perf branch August 29, 2023 18:45
Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants