microsoft / microsoft/TypeScript

Declaration emit spends significant CPU in getAliasForSymbolInContainer / getAlternativeContainingModules

オープン
#63,830 コメント 13 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Needs More Info
主要言語
Go
スター
111k
フォーク
14.3k
平均マージ
2日 4時間
マージ済み PR(30日)
132

説明

### Summary

While running `tsgo -b -f` on a large private project, declaration emit spends a significant amount of CPU time in symbol accessibility logic, especially `getAlternativeContainingModules` and `getAliasForSymbolInContainer`.

The project source cannot be shared, but I can provide sanitized pprof output and/or raw Go pprof profiles after checking that they do not contain private TypeScript source contents.

### Environment

- typescript-go commit: `804eb7a1a1a9b0722af207412921cc025dfbbd5a`
- tsgo version: `7.0.0-dev`
- Go version: `go1.26.0 linux/amd64`
- OS: Linux amd64
- Command shape: `./built/local/tsgo -b -f`

### Observed performance

Using `/usr/bin/time -v`:

```text
Elapsed wall time: 43.40s
User time: 196.33s
System time: 10.24s
CPU: 475%
Maximum resident set size: 4,264,424 KB
```

### CPU profile highlights

Profile command:
```
./built/local/tsgo -b -f --pprofDir
go tool pprof -top ./built/local/tsgo /-cpuprofile.pb.gz
go tool pprof -top -cum ./built/local/tsgo /-cpuprofile.pb.gz
```

Relevant excerpt:
```
Duration: 43.09s
Total samples: 208.55s

flat flat% cum cum%
3.00s 1.44% 42.62s 20.44% github.com/microsoft/typescript-go/internal/checker.(*Checker).getAlternativeContainingModules
1.36s 0.65% 37.27s 17.87% github.com/microsoft/typescript-go/internal/checker.(*Checker).getAliasForSymbolInContainer
0.15s 0.07% 21.60s 10.36% github.com/microsoft/typescript-go/internal/checker.(*Checker).getSymbolIfSameReference
0.26s 0.12% 12.96s 6.21% github.com/microsoft/typescript-go/internal/checker.(*Checker).resolveSymbolEx
7.99s 3.83% 7.99s 3.83% github.com/microsoft/typescript-go/internal/ast.IsNonLocalAlias
```

The cumulative profile suggests declaration emit repeatedly checks whether a symbol is accessible through alternative containing modules, and repeatedly scans exports in getAliasForSymbolInContainer.

### Allocation profile highlights

```
Total allocated: ~19.68GB
Maximum RSS from /usr/bin/time: ~4.26GB
```

### Local experiment

I tested a conservative local prototype that caches, per checker/container, the export candidates grouped by the same resolved/merged target symbol. It does not cache the final selected alias directly; it still sorts only the candidates for the currently queried target, to preserve the old selection behavior as closely as possible.

On the same private project:

```
Before: 43.40s wall, 4,264,424 KB max RSS
After: 37.64s wall, 4,210,296 KB max RSS
```

That is about a 13% wall time improvement on this workload.

Relevant tests passed locally:

```
GOCACHE=/tmp/tsgo-go-cache go test ./internal/checker
```

### Question

Would a per-container cache for alias candidates in getAliasForSymbolInContainer, or another cache around this symbol accessibility path, be acceptable? I am happy to share sanitized pprof text output, and possibly raw .pb.gz pprof files if that is useful.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

internal/checker の getAliasForSymbolInContainer と getAlternativeContainingModules から始め、続いて提供されている pprof コマンドと candidate-cache の実験を確認してください。GOCACHE=/tmp/tsgo-go-cache go test ./internal/checker を実行し、エイリアス選択の動作を維持しながら、報告されている CPU とアロケーションのコストを削減できれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
go, typescript
領域
compilers, performance
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
48/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。