Skip to content

Performance regression in resolving variables #5644

@d-biehl

Description

@d-biehl

RecommendationFinder is used in several places to produce "Did you mean...?" suggestions when variables or keywords are not found. It performs fuzzy string matching over all candidates, which is O(n×m) per lookup.

Affected locations

  1. robot.variables.notfound.variable_not_found() — iterates over all variable candidates
  2. robot.running.namespace.KeywordRecommendationFinder — iterates over all keywords from all libraries and resources (also affects --dryrun, since KeywordRunner passes recommend_on_failure=True by default)

(A third location in parsing.lexer.settings operates on a small fixed set of setting names, so it is not a performance concern.)

Note that there is already a TODO comment in

# TODO: Consider changing the default value of `recommend_on_failure` to False.

For tools that use Robot Framework's variable resolution programmatically (e.g., IDE language servers, static analysis tools, like RobotCode ), variable_not_found() may be triggered thousands of times during analysis. In large projects with many variables, this becomes a critical bottleneck.

Real-world impact: Analyzing 375 Robot Framework files took over 30 minutes, with the vast majority of time spent in RecommendationFinder. After monkey-patching variable_not_found to skip recommendations, the same analysis completes in under a minute. See: robotcodedev/robotcode#587

The KeywordRecommendationFinder in namespace.py has the same O(n×m) characteristic, though it primarily affects runtime execution and --dryrun rather than static analysis. RobotCode does not use RF's runtime namespace for keyword resolution, so this is not triggered in our case, but other tools or --dryrun with many missing keywords could be affected.

Current workaround

In RobotCode, we now monkey-patch variable_not_found across all modules that import it (robot.variables.notfound, finders, evaluation, store, robot.variables) to replace it with a version that simply raises VariableError without calling RecommendationFinder. This works, but it's fragile — it depends on internal module structure and could break with any refactoring of the robot.variables package.

Suggestion

A simple global flag like RECOMMENDATIONS_ENABLED (e.g., on RecommendationFinder or in robot.utils.recommendations) that can be set to False to skip all fuzzy matching would be sufficient and avoid the need for monkey-patching.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions