Skip to content

[PERF] Avoid repeated path matching when evaluating dependency rules #58

Description

@TristanKruse

[PERF] Avoid repeated path matching when evaluating dependency rules

Problem

On a generated project with 5,005 Python files and 13,738 import edges,
DependOnFileCondition.check() reuses the in-process graph as intended, but
gather_depend_on_file_violations() still scans every projected edge and calls
matches_pattern() repeatedly. The matcher normalizes or splits path labels
and runs a regex for each call. A suite of rules therefore spends most of its
time evaluating the same paths again.

In the comparison benchmark (ArchUnitPython 1.5.0 at commit
09c9d199dec095aaa60be227bfd7b5c2b7ffb107, Python 3.13.4, Windows 11),
the published fresh-process median for one direct boundary rule at 5,000 leaf
modules was 3.59 s. A separate exploratory phase profile showed:

Corpus Ten additional rules, current matcher Per-rule memoized matches Violation count
1,000 leaf modules 1.86 s 0.76 s 1,494 in both runs
5,000 leaf modules 18.2 s 7.4 s 7,494 in both runs

These phase timings are one-off diagnostics, not publication-grade speedup
claims. The ten rules varied source and target folders and ran in one process.
The graph cache was hit for every additional rule; at 5,000 modules the cache
lookup totaled about 0.003 s, while rule evaluation took about 17.8 s.

Proposed investigation and implementation

  1. Add a repeatable 1/10/50-rule benchmark linked to [Test] Benchmark for ArchUnitPython #55, including cold
    command latency, warm suite latency, p50/p95, and peak memory.
  2. Measure the number of unique source/target labels and repeated matcher
    calls. Preserve arbitrary compiled-regex and glob behavior.
  3. Match each unique label against each filter only once within a rule;
    normalize or split path labels once. Consider indexing outgoing edges by
    source if the simpler change does not remove enough work.
  4. Keep any cache bounded to a check or explicit suite context. Avoid a global
    cache that retains paths from unrelated projects or becomes stale after
    edits.

Acceptance criteria

  • Existing behavior and violation evidence remain unchanged for glob and regex
    filters, positive/negative rules, Windows paths, and empty-test protection.
  • Clean and seeded-violation benchmark corpora still produce the same results.
  • Report before/after median, p95, and memory for 1,000 and 5,000 modules,
    including 1/10/50-rule suites. The rule-evaluation phase should improve
    materially without a correctness or memory regression.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions