In my medium size project (about 20 modules, 10 forms, 4 classes), code inspection takes quite a long time (卤 5 min) in the latest build. It seams to take longer than in previous builds. Fixing things, obviously, takes longer.
But it doesn't crash and seams to function fine!
Also, I now use it to detect problems, fix them myself. This way it works very good.
To be honest, inspections weren't implemented with performance as a concern. As a result a number of them are rather inefficient and query State.AllDeclarations and State.BuiltInDeclarations with some [sometimes pretty nasty] LINQ that definitely can be improved, performance-wise.
Several inspections have shared concerns, such as the need to locate interface types and their implementations, or event handler procedures, or members' parameters, or need to filter out the built-in value types, etc. - and each inspection is currently doing it its own way, which is not only bug-prone, but also inefficient, and a rather significant technical debt.
Progress report - timings for this project with the current build:
Parsing: 4.6426s
Resolve Declarations: 21.8388s
Resolve References: 7.4707s
Inspections: 12.4649s
Total Runtime: 46.6875s
Times for individual inspections (in ms, descending):
Inspection Time (ms)
---------- ---------
ParameterCanBeByValInspection 4098
ParameterNotUsedInspection 2859
ProcedureNotUsedInspection 2705
ImplicitByRefParameterInspection 2656
ProcedureCanBeWrittenAsFunctionInspection 2150
MemberNotOnInterfaceInspection 607
ObjectVariableNotSetInspection 182
ObsoleteGlobalInspection 181
NonReturningFunctionInspection 178
SelfAssignedDeclarationInspection 158
FunctionReturnValueNotUsedInspection 125
WriteOnlyPropertyInspection 124
UndeclaredVariableInspection 100
ModuleScopeDimKeywordInspection 99
MoveFieldCloserToUsageInspection 96
MultipleFolderAnnotationsInspection 96
ImplicitPublicMemberInspection 91
OptionBaseInspection 82
MultipleDeclarationsInspection 81
MultilineParameterInspection 78
UntypedFunctionUsageInspection 73
ObsoleteTypeHintInspection 71
UseMeaningfulNameInspection 66
UnassignedVariableUsageInspection 57
HostSpecificExpressionInspection 33
ImplicitDefaultMemberAssignmentInspection 30
OptionExplicitInspection 13
HungarianNotationInspection 12
VariableNotAssignedInspection 10
VariableNotUsedInspection 9
VariableTypeNotDeclaredInspection 8
ImplicitVariantReturnTypeInspection 7
ImplicitActiveWorkbookReferenceInspection 3
ImplicitActiveSheetReferenceInspection 2
MissingAnnotationArgumentInspection 1
ObsoleteCallStatementInspection 1
EncapsulatePublicFieldInspection 0
AssignedByValParameterInspection 0
ConstantNotUsedInspection 0
DefaultProjectNameInspection 0
ObsoleteLetStatementInspection 0
EmptyStringLiteralInspection 0
ObsoleteCommentSyntaxInspection 0
Unsurprisingly, in ParaemterCanBeByVal the hotspot is right here:
var formEventHandlerScopes = State.FindFormEventHandlers().Select(handler => handler.Scope);
In that call tree, state.AllDeclarations is iterated twice. Once to get events, and once to get handlers. But UserDeclarations.ToList already iterated them all once already, and the next line goes:
var eventHandlerScopes = State.AllDeclarations.FindBuiltInEventHandlers().Concat(declarations.FindUserEventHandlers()).Select(e => e.Scope);
Refactoring that finder code out of RubberduckParserState extension methods and into State.DeclarationFinder calls will certainly further improve the performance here.
Wow @comintern I love this report as it is useful for benchmarking any vba code. Is this an ad hoc one or is available for anybody?
Closing this issue - performance is drastically improving in 2.0.12; the more expensive inspections have been given attention, and the State.DeclarationFinder cache is now used by most inspections.
Most helpful comment
Progress report - timings for this project with the current build:
Times for individual inspections (in ms, descending):