Saving inital Docs POC

This commit is contained in:
Luke Hagar
2025-11-09 22:22:52 -06:00
commit 95f23e2eb3
35 changed files with 5457 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
# Performance & Debugging Playbook
> [Docs Index](README.md) • [Repo README](../README.md) • [Testing & CI](testing-and-ci.md) • [Telemetry](telemetry-and-observability.md)
Volars language server is capable of analyzing massive Vue codebases, but only if you configure, profile, and debug it thoughtfully. This playbook covers every tool, environment flag, and technique for keeping your integrations fast and diagnosable.
## Philosophies
1. **Measure first** Always gather profiles/metrics before optimizing.
2. **Avoid duplication** Hook into Volars existing document, project, and TypeScript caches instead of re-reading files.
3. **Fail loudly** Surface configuration errors, missing schemas, and long-running operations via logs/telemetry so users know what to fix.
## Profiling Toolkit
### 1. Volars Built-in Tracing
Set environment variables before launching your LSP:
```bash
VOLAR_TRACE=protocol VOLAR_TRACE_DIR=/tmp/volar-trace npm run dev
```
- `protocol`: logs LSP traffic (requests, responses).
- `log`: internal logging.
In VS Code, set `"volar.vueserver.trace.server": "verbose"` to mirror the same behavior.
### 2. CPU & Heap Snapshots
Run the server with `--inspect`:
```bash
node --inspect-brk dist/server.js
```
- Use Chrome DevTools or VS Codes debugger to capture CPU profiles and heap snapshots.
- Focus on `provideDiagnostics` and `provideCompletionItems` if latency spikes while typing.
### 3. TypeScript Tracing
Enable TS compiler traces to see how TypeScript handles your virtual files:
```json
{
"vueCompilerOptions": {},
"tsserver": {
"logDirectory": "./.ts-log",
"trace": "messages"
}
}
```
Review `.ts-log/tsserver.log` for slow operations (`syntaxDiag`, `semanticDiag`, etc.).
## Hotspots & Mitigations
| Hotspot | Symptom | Mitigation |
| --- | --- | --- |
| Diagnostics re-run on every keystroke | CPU spikes | Debounce validations (`VALIDATION_DELAY`), skip unchanged documents, skip workspace diagnostics unless requested. |
| Re-parsing large snapshots | Memory churn | Cache AST/metadata on `IScriptSnapshot` instances and reuse in language-service plugins. |
| Schema fetch storms | Network latency | Cache with `cacheSchemas`, support offline `file://` URIs, respect HTTP cache headers. |
| Duplicate TypeScript programs | Slow TS features | Use `createTypeScriptProject` once per config and reuse the returned project. |
| Logging too verbose | Performance drag | Gate debug logging behind env vars / user settings. |
## Debugging Scenarios
### Scenario 1: Missing Diagnostics
Checklist:
1. Verify `provideDiagnostics` runs by logging entry/exit.
2. Ensure mappings have `verification: true`.
3. Confirm the documents language ID matches your plugins target.
4. Check `connection.sendDiagnostics` for errors (watch the LSP trace).
### Scenario 2: Incorrect Hover Text
1. Inspect the generated virtual code (`codeGen.getText()`) to ensure the content is what you expect.
2. Use `@volar/source-map` to verify the mapping covers the range you hovered.
3. Check that `provideHover` returns `MarkdownString`/`string` in the format the client expects (no stray triple backticks unless intended).
### Scenario 3: Memory Leak
1. Take heap snapshots before/after opening large files.
2. Confirm you dispose snapshots (call `dispose` on `IScriptSnapshot` if you allocate custom ones).
3. Remove references to old projects/documents when workspace folders change (watch `server.workspaceFolders.onDidChange`).
### Scenario 4: Take Over Mode Conflicts
1. Verify only one TypeScript server is running (disable built-in TS in VS Code when using Volar).
2. Check `tsserver.log` to ensure the Volar TS plugin is loaded once per project.
3. Provide documentation/instructions for users to disable conflicting extensions.
## Logging & Diagnostics
### Structured Logging
```ts
const log = (message: string, data?: unknown) => {
connection.console.info(`[json-yaml] ${message} ${data ? JSON.stringify(data) : ''}`);
};
```
- Use `connection.console` for logs visible in the clients output channel.
- Reserve `console.error` for actionable failures (schema fetch errors, config parse failures).
### Telemetry Hooks
```ts
connection.telemetry.logEvent({
type: 'json-yaml.schemaFetch',
uri,
duration,
success,
});
```
- Emit events for expensive operations (schema fetch, TypeScript project reload) to help downstream clients aggregate data.
- Keep personally identifiable information out of telemetry payloads.
### Work Done Progress
```ts
const progress = await connection.window.createWorkDoneProgress();
progress.begin('Fetching schemas', 0, 'Starting');
progress.report(50, 'Halfway');
progress.done();
```
- Use for long-running operations (initial project load, workspace diagnostics).
## Best Practices for Performance-Sensitive Hooks
### Diagnostics
- Track pending validations per URI; cancel the previous timer when new edits arrive.
- Compare document versions before publishing to avoid stale updates.
- Use workspace diagnostics sparingly; provide a manual “Refresh Diagnostics” command if theyre expensive in your environment.
### Completions
- Precompute completion data (e.g., known components, JSON schema values) and reuse across requests.
- Return resolved items via `resolveCompletionItem` only when the client asks; keep the initial list lightweight.
### Hovers
- Avoid heavy computation in `provideHover`. Pre-parse metadata (docstrings, schema descriptions) when loading the project.
- Cache hover results for stable nodes (component props) and invalidate when the underlying file changes.
### TypeScript Integration
- Use `createTypeScriptProject` once per config and share the result across all language services to leverage TSs incremental caching.
- Avoid calling `project.reload()` unless absolutely necessary; prefer targeted invalidation (e.g., `language.scripts.delete(uri)`).
## Troubleshooting Checklist
1. **Is the issue limited to specific files?** Inspect their generated output and mappings.
2. **Does it happen after hot reload or configuration changes?** Check `applyConfiguration` to ensure youre not re-registering plugins or leaking state.
3. **Is TypeScript raising errors?** Examine `tsserver.log` and ensure your TS plugin is registering correctly.
4. **Are you duplicating watchers?** One file watcher per project is sufficient; extra watchers can saturate the event loop.
5. **Is schema resolution slow?** Provide `resolveWorkspaceUri` to avoid hitting network paths unnecessarily and cache responses aggressively.
## When to Ask for Help
- Capture logs (`VOLAR_TRACE`, `tsserver.log`, heap/CPU profiles) and file an issue with the relevant data.
- Include your `tsconfig`/`jsconfig`, workspace structure, and steps to reproduce.
- Mention whether Take Over Mode is enabled and which editor youre using.
By following this playbook, you can keep Volar integrations responsive while making it easy to diagnose issues when they arise. Profile often, log judiciously, and share configuration knobs with your users so they can tailor performance to their workflow.