mirror of
https://github.com/nushell/nushell.git
synced 2026-10-28 17:05:03 +08:00
Check each module once when deciding whether to reload a cached module ## Description When a module that has already been parsed is imported again, `parse_module_file` calls `module_needs_reloading` to check whether any file in the module's tree has changed on disk. That walk recurses through `submodules` and `imported_modules` without tracking which modules it has visited, so a module reachable through several paths is re-read once per *path*. That's common in practice: a `mod.nu` that `export use`s its sibling files, where most siblings also `use` a few shared helpers. In the repro from the issue, every extra `use nested` of a 9-file module re-reads its files ~133 times; with a real 22-file library it's ~412 reads per import. Linux mostly hides this because file opens are cheap, but on Windows it dominates parse time, and the LSP pays it on every keystroke. This PR adds a `seen` set for the duration of the walk, so each reachable module's file is read at most once per check. Skipping an already-seen module is safe: `any()` short-circuits on the first change, so a module seen again has already been found unchanged. I also extracted the read-and-compare into a separate `module_file_changed` function. Measured on Windows with the repro script from the issue (`nu -n repro.nu`): | importers | before | after | | --------: | -----: | ----: | | 1 | 34.9 ms | 28.4 ms | | 2 | 51.2 ms | 29.2 ms | | 5 | 97.5 ms | 32.4 ms | | 10 | 179.0 ms | 38.3 ms | Per extra importer: **16.0 ms → 1.1 ms**. In my real-world case (a 13-file module importing a 22-file library from most of its files), parsing on Windows went from ~3.1 s to the point where the LSP is responsive again. ## User-facing changes (Release notes) Improved performance when the same module is imported from many places. Nushell no longer re-reads a module's files once for every import path when checking whether a cached module has changed. This especially speeds up parsing and the language server on Windows for libraries whose files import each other. ## Additional notes - fixes #19226 - `cargo test -p nu-parser` and `cargo test --test tests -- modules::` pass; the second runs the module reload tests, including the new `reload_module_reached_through_several_imports`. - Behaviour is unchanged: a modified file anywhere in the tree still triggers a reload. Only repeat visits of the same module within one check are skipped.