Avatar for the astral-sh user
astral-sh
ruff
Instrumentation
Wall Time
BlogDocsChangelog

[ty] Add caching for submodule completion suggestions

#19408Merged
Comparing
ag/submodule-caching
(
ddae85e
) with
main
(
99d0ac6
)
CodSpeed Performance Gauge
0%
Improvements
0
Regressions
0
Untouched
41
New
0
Dropped
0
Ignored
0

Benchmarks

Passed

ty_check_file[cold]
crates/ruff_benchmark/benches/ty.rs::check_file::benchmark_cold::ty_check_file[cold]
CodSpeed Performance Gauge
0%
125.8 ms
125.5 ms
ty_micro[complex_constrained_attributes_2]
crates/ruff_benchmark/benches/ty.rs::micro::benchmark_complex_constrained_attributes_2::ty_micro[complex_constrained_attributes_2]
CodSpeed Performance Gauge
0%
60.7 ms
60.7 ms
ty_micro[many_enum_members]
crates/ruff_benchmark/benches/ty.rs::micro::benchmark_many_enum_members::ty_micro[many_enum_members]
CodSpeed Performance Gauge
0%
112.2 ms
112.1 ms
ty_micro[many_tuple_assignments]
crates/ruff_benchmark/benches/ty.rs::micro::benchmark_many_tuple_assignments::ty_micro[many_tuple_assignments]
CodSpeed Performance Gauge
0%
141.5 ms
141.4 ms
ty_micro[many_string_assignments]
crates/ruff_benchmark/benches/ty.rs::micro::benchmark_many_string_assignments::ty_micro[many_string_assignments]
CodSpeed Performance Gauge
0%
74.7 ms
74.7 ms
linter/default-rules[numpy/globals.py]
crates/ruff_benchmark/benches/linter.rs::default_rules::benchmark_default_rules::linter/default-rules[numpy/globals.py]
CodSpeed Performance Gauge
0%
195.4 µs
195.4 µs
linter/all-rules[numpy/globals.py]
crates/ruff_benchmark/benches/linter.rs::all_rules::benchmark_all_rules::linter/all-rules[numpy/globals.py]
CodSpeed Performance Gauge
0%
693.6 µs
693.6 µs
linter/all-with-preview-rules[numpy/globals.py]
crates/ruff_benchmark/benches/linter.rs::preview_rules::benchmark_preview_rules::linter/all-with-preview-rules[numpy/globals.py]
CodSpeed Performance Gauge
0%
786 µs
785.9 µs
linter/default-rules[unicode/pypinyin.py]
crates/ruff_benchmark/benches/linter.rs::default_rules::benchmark_default_rules::linter/default-rules[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
379.5 µs
379.5 µs
linter/all-with-preview-rules[large/dataset.py]
crates/ruff_benchmark/benches/linter.rs::preview_rules::benchmark_preview_rules::linter/all-with-preview-rules[large/dataset.py]
CodSpeed Performance Gauge
0%
20.9 ms
20.9 ms
linter/all-with-preview-rules[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/linter.rs::preview_rules::benchmark_preview_rules::linter/all-with-preview-rules[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
4.9 ms
4.9 ms
linter/all-rules[pydantic/types.py]
crates/ruff_benchmark/benches/linter.rs::all_rules::benchmark_all_rules::linter/all-rules[pydantic/types.py]
CodSpeed Performance Gauge
0%
8.4 ms
8.4 ms
linter/default-rules[pydantic/types.py]
crates/ruff_benchmark/benches/linter.rs::default_rules::benchmark_default_rules::linter/default-rules[pydantic/types.py]
CodSpeed Performance Gauge
0%
2 ms
2 ms
linter/default-rules[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/linter.rs::default_rules::benchmark_default_rules::linter/default-rules[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
968.2 µs
968.2 µs
linter/all-with-preview-rules[pydantic/types.py]
crates/ruff_benchmark/benches/linter.rs::preview_rules::benchmark_preview_rules::linter/all-with-preview-rules[pydantic/types.py]
CodSpeed Performance Gauge
0%
10 ms
10 ms
linter/default-rules[large/dataset.py]
crates/ruff_benchmark/benches/linter.rs::default_rules::benchmark_default_rules::linter/default-rules[large/dataset.py]
CodSpeed Performance Gauge
0%
4.1 ms
4.1 ms
formatter[large/dataset.py]
crates/ruff_benchmark/benches/formatter.rs::formatter::benchmark_formatter::formatter[large/dataset.py]
CodSpeed Performance Gauge
0%
9.5 ms
9.5 ms
linter/all-rules[unicode/pypinyin.py]
crates/ruff_benchmark/benches/linter.rs::all_rules::benchmark_all_rules::linter/all-rules[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
1.8 ms
1.8 ms
formatter[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/formatter.rs::formatter::benchmark_formatter::formatter[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
1.9 ms
1.9 ms
formatter[pydantic/types.py]
crates/ruff_benchmark/benches/formatter.rs::formatter::benchmark_formatter::formatter[pydantic/types.py]
CodSpeed Performance Gauge
0%
3.6 ms
3.6 ms
linter/all-rules[large/dataset.py]
crates/ruff_benchmark/benches/linter.rs::all_rules::benchmark_all_rules::linter/all-rules[large/dataset.py]
CodSpeed Performance Gauge
0%
17.1 ms
17.1 ms
parser[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/parser.rs::parser::benchmark_parser::parser[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
934.2 µs
934.2 µs
lexer[large/dataset.py]
crates/ruff_benchmark/benches/lexer.rs::lexer::benchmark_lexer::lexer[large/dataset.py]
CodSpeed Performance Gauge
0%
1.1 ms
1.1 ms
linter/all-rules[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/linter.rs::all_rules::benchmark_all_rules::linter/all-rules[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
4 ms
4 ms
formatter[unicode/pypinyin.py]
crates/ruff_benchmark/benches/formatter.rs::formatter::benchmark_formatter::formatter[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
662.9 µs
662.9 µs
parser[pydantic/types.py]
crates/ruff_benchmark/benches/parser.rs::parser::benchmark_parser::parser[pydantic/types.py]
CodSpeed Performance Gauge
0%
2 ms
2 ms
parser[large/dataset.py]
crates/ruff_benchmark/benches/parser.rs::parser::benchmark_parser::parser[large/dataset.py]
CodSpeed Performance Gauge
0%
5 ms
5 ms
lexer[pydantic/types.py]
crates/ruff_benchmark/benches/lexer.rs::lexer::benchmark_lexer::lexer[pydantic/types.py]
CodSpeed Performance Gauge
0%
490.5 µs
490.6 µs
formatter[numpy/globals.py]
crates/ruff_benchmark/benches/formatter.rs::formatter::benchmark_formatter::formatter[numpy/globals.py]
CodSpeed Performance Gauge
0%
242.1 µs
242.1 µs
linter/all-with-preview-rules[unicode/pypinyin.py]
crates/ruff_benchmark/benches/linter.rs::preview_rules::benchmark_preview_rules::linter/all-with-preview-rules[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
2.1 ms
2.1 ms
lexer[numpy/ctypeslib.py]
crates/ruff_benchmark/benches/lexer.rs::lexer::benchmark_lexer::lexer[numpy/ctypeslib.py]
CodSpeed Performance Gauge
0%
219.2 µs
219.2 µs
ty_micro[complex_constrained_attributes_1]
crates/ruff_benchmark/benches/ty.rs::micro::benchmark_complex_constrained_attributes_1::ty_micro[complex_constrained_attributes_1]
CodSpeed Performance Gauge
0%
61.2 ms
61.2 ms
ty_check_file[incremental]
crates/ruff_benchmark/benches/ty.rs::check_file::benchmark_incremental::ty_check_file[incremental]
CodSpeed Performance Gauge
0%
5.6 ms
5.6 ms
parser[unicode/pypinyin.py]
crates/ruff_benchmark/benches/parser.rs::parser::benchmark_parser::parser[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
322.4 µs
322.5 µs
lexer[unicode/pypinyin.py]
crates/ruff_benchmark/benches/lexer.rs::lexer::benchmark_lexer::lexer[unicode/pypinyin.py]
CodSpeed Performance Gauge
0%
75.7 µs
75.8 µs
parser[numpy/globals.py]
crates/ruff_benchmark/benches/parser.rs::parser::benchmark_parser::parser[numpy/globals.py]
CodSpeed Performance Gauge
0%
106.9 µs
106.9 µs
lexer[numpy/globals.py]
crates/ruff_benchmark/benches/lexer.rs::lexer::benchmark_lexer::lexer[numpy/globals.py]
CodSpeed Performance Gauge
0%
29.4 µs
29.4 µs
hydra-zen
crates/ruff_benchmark/benches/ty.rs::project::hydra::project::hydra-zen
CodSpeed Performance Gauge
0%
870.7 ms
872.1 ms
attrs
crates/ruff_benchmark/benches/ty.rs::project::attrs::project::attrs
CodSpeed Performance Gauge
0%
398.6 ms
400.3 ms
anyio
crates/ruff_benchmark/benches/ty.rs::project::anyio::project::anyio
CodSpeed Performance Gauge
-1%
915.4 ms
921 ms
DateType
crates/ruff_benchmark/benches/ty.rs::project::datetype::project::DateType
CodSpeed Performance Gauge
-1%
249.2 ms
250.8 ms

Commits

Click on a commit to change the comparison range
Base
main
99d0ac6
0%
[ty] Add caching for submodule completion suggestions This change makes it so we aren't doing a directory traversal every time we ask for completions from a module. Specifically, submodules that aren't attributes of their parent module can only be discovered by looking at the directory tree. But we want to avoid doing a directory scan unless we think there are changes. To make this work, this change does a little bit of surgery to `FileRoot`. Previously, a `FileRoot` was only used for library search paths. Its revision was bumped whenever a file in that tree was added, deleted or even modified (to support the discovery of `pth` files and changes to its contents). This generally seems fine since these are presumably dependency paths that shouldn't change frequently. In this change, we add a `FileRoot` for the project. But having the `FileRoot`'s revision bumped for every change in the project makes caching based on that `FileRoot` rather ineffective. That is, cache invalidation will occur too aggressively. To the point that there is little point in adding caching in the first place. To mitigate this, a `FileRoot`'s revision is only bumped on a change to a child file's contents when the `FileRoot` is a `LibrarySearchPath`. Otherwise, we only bump the revision when a file is created or added. The effect is that, at least in VS Code, when a new module is added or removed, this change is picked up and the cache is properly invalidated. Other LSP clients with worse support for file watching (which seems to be the case for the CoC vim plugin that I use) don't work as well. Here, the cache is less likely to be invalidated which might cause completions to have stale results. Unless there's an obvious way to fix or improve this, I propose punting on improvements here for now.
ddae85e
14 days ago
by BurntSushi
© 2025 CodSpeed Technology
Home Terms Privacy Docs