-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Conversation
b7d0ebd
to
24a93f8
Compare
✅ 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', |
There was a problem hiding this comment.
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 🤷🏻
process.exitCode = 1; | ||
return; |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
let baseType; | ||
if (process.env.AWSLINT_BASE_CONSTRUCT && !CoreTypes.isCfnResource(e.ctx.classType)) { | ||
baseType = e.ctx.core.baseConstructClass; | ||
} else { | ||
baseType = e.ctx.core.constructClass; | ||
} |
There was a problem hiding this comment.
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.
for (const fqn of Object.values(CoreTypesFqn)) { | ||
if (!this.sys.tryFindFqn(fqn)) { | ||
throw new Error(`core FQN type not found: ${fqn}`); | ||
} | ||
} |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
const baseType = process.env.AWSLINT_BASE_CONSTRUCT ? e.ctx.resource.core.baseConstructClass | ||
: e.ctx.resource.core.constructClass; | ||
const baseType = e.ctx.resource.core.baseConstructClass; |
There was a problem hiding this comment.
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.
.findAllConstructs(assembly) | ||
.filter(c => CoreTypes.isResourceClass(c.classType)) |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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)
24a93f8
to
9bb8e6b
Compare
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; |
There was a problem hiding this comment.
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.
packages/aws-cdk-lib/awslint.json
Outdated
There was a problem hiding this comment.
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.
There was a problem hiding this 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. 😅
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 CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
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). |
Reduces runtime of
awslint
againstaws-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)
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license