Rubberduck: Build 2.0.10 code inspections take a long time

Created on 5 Jan 2017  路  5Comments  路  Source: rubberduck-vba/Rubberduck

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.

enhancement feature-inspections performance technical-debt

Most helpful comment

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

All 5 comments

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.

Was this page helpful?
0 / 5 - 0 ratings