Skip to content

Commit 93f701c

Browse files
committed
Saving a file no longer re-analyses every other open tab
1 parent e722043 commit 93f701c

9 files changed

Lines changed: 668 additions & 52 deletions

File tree

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6060
- **Argument checking no longer slows down quadratically with file size.** The argument-count and argument-type checks know the byte offset of every call they inspect, but used to convert it into an editor line/column position and immediately back again before looking up the called function. Each of those conversions re-read the file from the beginning to count characters, so the cost of checking one call grew with the size of the file around it and a file with thousands of calls spent nearly all its time on offset arithmetic. The offset is now used directly. On a 370 KB file containing 2200 calls the two checks together drop from 13.7 seconds to 0.2, taking the whole file from 16.7 seconds to 3.4, and analysing the project it belongs to is close to three times faster.
6161
- **Faster workspace symbol search.** Matching a symbol against the "Go to Symbol in Workspace" query no longer allocates a lowercased copy of every class, method, property, constant, and function name in the project on each keystroke; matching is now done byte-wise in place for the common case of ASCII identifiers.
6262
- **Faster Eloquent scope-method resolution.** Injecting a model's scope methods onto its Builder used to re-walk the model's full inheritance chain (traits and parent classes) from scratch on every `Builder<Model>` instantiation. That base resolution is now cached, so a file with many instantiations of the same model's Builder resolves its scopes once instead of repeatedly.
63+
- **Saving a file no longer re-analyses every other open tab.** A save used to re-run the full diagnostic pass, the most expensive thing PHPantom does, on all open files in case any of them depended on the saved one. It now works out what the save actually changed (a class, one of its members, a function, a constant) and re-analyses only the open files that mention one of those names. Editing a method body reaches only the files that use the class, and renaming or retyping a member reaches only the files that use that member; unrelated tabs are left alone, so completion and hover stay responsive right after a save. Cases the comparison cannot narrow, such as saving a Laravel config, translation, or route file, still refresh every open file as before.
6364

6465
### Removed
6566

docs/todo.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ unlikely to move the needle for most users.
199199
| P30 | [Evaluate migrating parse/resolve/docblock pipeline to `mago-hir`](todo/performance.md#p30-evaluate-migrating-parseresolvedocblock-pipeline-to-mago-hir) (parked — re-evaluated at mago 1.45.0, still no `mago-hir` consumers upstream) | Medium-High | High |
200200
| P47 | [The resolved-class cache lock caps concurrent class resolution](todo/performance.md#p47-the-resolved-class-cache-lock-caps-concurrent-class-resolution) | Medium | Medium-High |
201201
| P16 | [Pre-parsed stub format (eliminate raw PHP embedding)](todo/performance.md#p16-pre-parsed-stub-format-eliminate-raw-php-embedding) | High | Medium-High |
202-
| P22 | [Signature change re-queues slow diagnostics for every open file](todo/performance.md#p22-signature-change-re-queues-slow-diagnostics-for-every-open-file) | Medium-High | Medium |
203202
| P3 | Parallel pre-filter in `find_implementors` | Low-Medium | Medium |
204203
| P6 | O(n²) transitive eviction in `evict_fqn` | Low | Low |
205204
| P15 | [Two-phase stub index construction (eliminate `RwLock` on stub maps)](todo/performance.md#p15-two-phase-stub-index-construction-eliminate-rwlock-on-stub-maps) | Low | Medium |

docs/todo/performance.md

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -497,44 +497,6 @@ diagnostic layer.
497497

498498
---
499499

500-
## P22. Signature change re-queues slow diagnostics for every open file
501-
502-
**Impact: Medium-High · Effort: Medium**
503-
504-
When a file is saved, `schedule_diagnostics_for_open_files`
505-
(`src/diagnostics/mod.rs`, called from `did_save` in
506-
`src/server.rs`) queues **all** open files (minus the saved one)
507-
for a full slow-diagnostic pass — unknown classes, unknown
508-
members, argument checks. The per-file cost of that pass is the
509-
most expensive thing the server does (see the Appendix: tens of
510-
seconds on pathological files, hundreds of ms on ordinary ones).
511-
512-
A user with 20 tabs open therefore pays 20 full-file analysis
513-
passes per save, regardless of whether those files reference the
514-
edited class at all. (This used to fire on every signature-changing
515-
edit; it is now save-gated, which caps the frequency but not the
516-
O(open files) fan-out.) During the burst the diagnostic worker
517-
saturates blocking threads that completion/hover also need.
518-
519-
### Fix
520-
521-
Queue only files that can observe the change. The resolved-class
522-
cache already maintains a dependency index for transitive
523-
eviction (`evict_fqn`), and ER4 tracks which members changed.
524-
Build a reverse map (FQN → open files that reference it) — either
525-
from each file's `resolved_names` (which byte-offset FQN lookups
526-
already exist for) or by recording, during each diagnostic pass,
527-
which FQNs the pass touched. On signature change, queue only the
528-
dependent files. Falls back to all-open-files when the dependency
529-
data is missing (e.g. right after startup).
530-
531-
Synergy: P21 (offset-shifting) reduces the cost of re-diagnosing
532-
the *edited* file; this item reduces the *count* of other files
533-
re-diagnosed. Together they make the slow pass proportional to
534-
the blast radius of an edit.
535-
536-
---
537-
538500
## P46. `mago-phpdoc-syntax` cannot parse `@method static (…) name()`
539501

540502
**Impact: Low · Effort: Low (upstream)**

0 commit comments

Comments
 (0)