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(awslint): linting is slow #27860

Merged
merged 2 commits into from
Nov 17, 2023
Merged

Conversation

mrgrain
Copy link
Contributor

@mrgrain mrgrain commented Nov 6, 2023

Reduces runtime of awslint against aws-cdk-lib from ~70s down to ~15s.

Speed up 1: Reduce rule definitions (~1s)
Speed up 2: Make core checks fqn based only (~5s)
Speed up 3: Optimize code paths to defer expensive checks (~4s)
Speed up 4: Locked typesystem (~25s)
Speed up 5: Faster camel casing (~15s)

giphy


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team November 6, 2023 19:57
@github-actions github-actions bot added the p2 label Nov 6, 2023
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Nov 6, 2023
aws-cdk-automation

This comment was marked as outdated.

@mrgrain mrgrain force-pushed the mrgrain/chore/awslint-go-vroom-vroom branch 4 times, most recently from b7d0ebd to 24a93f8 Compare November 9, 2023 15:49
@mrgrain mrgrain added pr-linter/exempt-test The PR linter will not require test changes pr-linter/exempt-integ-test The PR linter will not require integ test changes labels Nov 9, 2023
@aws-cdk-automation aws-cdk-automation dismissed their stale review November 9, 2023 15:51

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@@ -15,7 +15,7 @@ module.exports = {
parserOptions: {
ecmaVersion: '2018',
sourceType: 'module',
project: './tsconfig.json',
project: __dirname + '/tsconfig.json',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was just broken before 🤷🏻

Comment on lines +53 to +54
process.exitCode = 1;
return;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unrelated change to use best practice.

});

async function loadModule(dir: string) {
const ts = new reflect.TypeSystem();
await ts.load(dir, { validate: false }); // Don't validate to save 66% of execution time (20s vs 1min).
// We run 'awslint' during build time, assemblies are guaranteed to be ok.

// We won't load any more assemblies. Lock the typesystem to benefit from performance improvements.
ts.lock();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This enables performance improvements in jsii-reflect that rely on a locked typesystem.

@@ -0,0 +1,18 @@
import * as changeCase from 'change-case';
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 tested a bunch.

fast-case is the fastest, but cannot deal with cases like DBProxy (converts it to dBProxy)
lodash and change-case are of similar speed
camelcase is by far the slowest.

@@ -0,0 +1,18 @@
import * as changeCase from 'change-case';

function cachedTransform(transform: (x: string) => string): (x: string) => string {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Throwing this in for good measure, so we never convert the same string twice. It saves 3-4s.

@@ -126,7 +126,7 @@ apiLinter.add({
return;
}

if (type.type.fqn === e.ctx.core.constructClass.fqn) {
if (type.type.fqn === e.ctx.core.baseConstructClassFqn) {
Copy link
Contributor Author

@mrgrain mrgrain Nov 9, 2023

Choose a reason for hiding this comment

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

Bypasses loading of the type just to compare the fqn.
I am making the assumption here that our core types are well tested and definitely exist in the assembly. If not jsii would blow up anyway.

Comment on lines -103 to -108
let baseType;
if (process.env.AWSLINT_BASE_CONSTRUCT && !CoreTypes.isCfnResource(e.ctx.classType)) {
baseType = e.ctx.core.baseConstructClass;
} else {
baseType = e.ctx.core.constructClass;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This check was redundant because e.ctx.core.baseConstructClass and e.ctx.core.constructClass are the same.

Comment on lines -162 to -166
for (const fqn of Object.values(CoreTypesFqn)) {
if (!this.sys.tryFindFqn(fqn)) {
throw new Error(`core FQN type not found: ${fqn}`);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is already checked by jsii

const baseType = process.env.AWSLINT_BASE_CONSTRUCT ? e.ctx.resource.core.baseConstructClass :
e.ctx.resource.core.constructClass;
const baseType = e.ctx.resource.core.baseConstructClass;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both values are the same.

Comment on lines -95 to +94
const baseType = process.env.AWSLINT_BASE_CONSTRUCT ? e.ctx.resource.core.baseConstructClass
: e.ctx.resource.core.constructClass;
const baseType = e.ctx.resource.core.baseConstructClass;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both values are the same.

Comment on lines -35 to -36
.findAllConstructs(assembly)
.filter(c => CoreTypes.isResourceClass(c.classType))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This loops twice over all constructs.

@@ -266,7 +265,7 @@ function tryResolveCfnResource(resourceClass: reflect.ClassType): CfnResourceRef
}

// try to resolve through ancestors
for (const base of resourceClass.getAncestors()) {
for (const base of resourceClass.ancestors) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using the memoized version of getAncestors

Speed up 2: Make core checks fqn based only (~4s)
Speed up 3: Optimize code paths to defer expensive checks (~3s)
Speed up 4: Locked typesystem (~25s)
Speed up 5: Faster camel casing (~15s)
@mrgrain mrgrain force-pushed the mrgrain/chore/awslint-go-vroom-vroom branch from 24a93f8 to 9bb8e6b Compare November 17, 2023 15:38
@mrgrain mrgrain marked this pull request as ready for review November 17, 2023 15:39
if (documentable.overrides.isClassType() || documentable.overrides.isInterfaceType()) {
const baseMembers = documentable.overrides.allMembers.filter(m => m.name === documentable.name);
if ((documentable instanceof reflect.Property || documentable instanceof reflect.Method)) {
const overrides = documentable.overrides;
Copy link
Contributor Author

@mrgrain mrgrain Nov 9, 2023

Choose a reason for hiding this comment

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

Make sure we only query (the expensive) overrides if we really need to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Folding a bunch of rules into * rules. This is mostly enums.

@aws-cdk-automation aws-cdk-automation added the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Nov 17, 2023
@vinayak-kukreja vinayak-kukreja self-assigned this Nov 17, 2023
Copy link
Contributor

@vinayak-kukreja vinayak-kukreja left a comment

Choose a reason for hiding this comment

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

This is amazing 😍

/**
* @deprecated - use `CoreTypes.constructClass()` or `CoreTypes.baseConstructClass()` as appropriate
*/
public readonly ROOT_CLASS: reflect.ClassType; // constructs.Construct
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we the only ones using this package? If not, this would be breaking for any users referring it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's public but in "dev preview". Has been for ages.
https://www.npmjs.com/package/awslint

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Never mind, this isn't even a public API. It's not exported at the top-level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's also not a library. It's a cli tool. 😅

@aws-cdk-automation aws-cdk-automation removed the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Nov 17, 2023
Copy link
Contributor

mergify bot commented Nov 17, 2023

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 6f2f40e
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot merged commit 0607b2c into main Nov 17, 2023
9 checks passed
@mergify mergify bot deleted the mrgrain/chore/awslint-go-vroom-vroom branch November 17, 2023 18:36
Copy link
Contributor

mergify bot commented Nov 17, 2023

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS. p2 pr-linter/exempt-integ-test The PR linter will not require integ test changes pr-linter/exempt-test The PR linter will not require test changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants