# 帳票設計書 2-Startup Performance Report

## 概要

本ドキュメントは、VS Codeの起動パフォーマンス計測結果をMarkdown形式で表示するStartup Performance Report機能の帳票出力仕様を定義するものである。

### 本帳票の処理概要

Startup Performance Reportは、VS Codeの起動時間を詳細に分析するための診断レポートを生成する機能である。

**業務上の目的・背景**：VS Codeの起動が遅いと感じた際に、どのフェーズで時間がかかっているかを特定するための情報を提供する。開発者やパワーユーザーがパフォーマンス問題を診断し、拡張機能や設定の最適化を行うための基礎データとなる。

**帳票の利用シーン**：コマンドパレットから「Developer: Startup Performance」を実行した際に、エディタ内にMarkdown形式のレポートが表示される。起動が遅いと感じた際のトラブルシューティングや、拡張機能のパフォーマンス影響を調査する際に使用される。

**主要な出力内容**：
1. System Info（製品バージョン、OS、CPU、メモリ、VM判定等）
2. Performance Marks（各起動フェーズの所要時間）
3. Extension Activation Stats（拡張機能のアクティベーション統計）
4. Terminal Stats（ターミナル関連のパフォーマンスマーク）
5. Workbench Contributions Blocking Restore（起動をブロックするコントリビューション）
6. Raw Perf Marks（生のパフォーマンスマーク）
7. Resource Timing Stats（リソース読み込み統計）

**帳票の出力タイミング**：コマンド実行時に動的に生成され、専用のエディタペインに表示される。

**帳票の利用者**：VS Code開発者、パワーユーザー、拡張機能開発者

## 帳票種別

診断レポート / パフォーマンスレポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Performance Editor | `perf:Startup Performance` | Developer: Startup Performance コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Markdown（エディタ内表示） |
| 用紙サイズ | N/A（エディタペイン内表示） |
| 向き | N/A |
| ファイル名 | N/A（仮想ドキュメント） |
| 出力方法 | TextResourceEditorInput経由でエディタに表示 |
| 文字コード | UTF-8 |

### 表示設定

| 項目 | 内容 |
|-----|------|
| Word Wrap | Off（自動折り返し無効） |
| Language Mode | Markdown |
| URI Scheme | perf |

## 帳票レイアウト

### レイアウト概要

レポートは複数のセクションで構成され、各セクションがMarkdownの見出しとテーブルで表現される。

```
┌─────────────────────────────────────┐
│         ## System Info              │
│    (Product, OS, CPU, Memory等)     │
├─────────────────────────────────────┤
│      ## Performance Marks           │
│    (起動フェーズ別所要時間)           │
├─────────────────────────────────────┤
│   ## Extension Activation Stats     │
│    (拡張機能アクティベーション統計)    │
├─────────────────────────────────────┤
│       ## Terminal Stats             │
│    (ターミナル関連マーク)             │
├─────────────────────────────────────┤
│ ## Workbench Contributions          │
│   Blocking Restore                  │
├─────────────────────────────────────┤
│      ## Raw Perf Marks              │
│    (各プロセスの生マーク)             │
├─────────────────────────────────────┤
│    ## Resource Timing Stats         │
│    (リソース読み込み統計)             │
└─────────────────────────────────────┘
```

### System Info部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Product Name/Version | 製品名とバージョン | productService.nameShort, productService.version, productService.commit | `* {name}: {version} ({commit})` |
| 2 | OS | OS名とリリース | metrics.platform, metrics.release | `* OS: {platform}({release})` |
| 3 | CPUs | CPU情報 | metrics.cpus | `* CPUs: {model}({count} x {speed})` |
| 4 | Memory (System) | システムメモリ | metrics.totalmem, metrics.freemem | `* Memory(System): {total} GB({free}GB free)` |
| 5 | Memory (Process) | プロセスメモリ | metrics.meminfo | `* Memory(Process): {workingSet} MB working set` |
| 6 | VM (likelihood) | VM判定 | metrics.isVMLikelyhood | `* VM(likelihood): {percent}%` |
| 7 | Initial Startup | 初回起動フラグ | metrics.initialStartup | `* Initial Startup: {boolean}` |
| 8 | Other Windows | 他ウィンドウ数 | metrics.windowCount | `* Has {n} other windows` |
| 9 | Screen Reader Active | スクリーンリーダー | metrics.hasAccessibilitySupport | `* Screen Reader Active: {boolean}` |
| 10 | Empty Workspace | 空ワークスペース | metrics.emptyWorkbench | `* Empty Workspace: {boolean}` |

### Performance Marks部

| No | 項目名 | 説明 | データ取得元 | 列 |
|----|-------|------|-------------|-----|
| 1 | What | 処理内容 | 固定ラベル | 1列目 |
| 2 | Duration | 所要時間(ms) | metrics.timers.* | 2列目 |
| 3 | Process | プロセス種別 | 固定値 | 3列目 |
| 4 | Info | 追加情報 | 動的 | 4列目 |

**主要な計測項目**：
- import(main.js) - メインバンドル読み込み
- start => app.isReady - アプリ準備完了
- nls:start => nls:end - NLS生成
- run main.js - メインバンドル実行
- start crash reporter - クラッシュレポーター起動
- serve main IPC handle - IPC準備
- create window - ウィンドウ作成
- app.isReady => window.loadUrl() - URL読み込み開始
- window.loadUrl() => begin to import - レンダラー初期化
- import(workbench.desktop.main.js) - ワークベンチ読み込み
- wait for window config - 設定待機
- init storage - ストレージ初期化
- init workspace service - ワークスペースサービス初期化
- register extensions & spawn extension host - 拡張機能登録
- restore viewlets/panels/editors - UI復元
- workbench ready - 準備完了

### Extension Activation Stats部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Extension | 拡張機能ID | extensionId | テーブル1列目 |
| 2 | Eager | 起動時ロードか | activationReason.startup | テーブル2列目 |
| 3 | Load Code | コード読み込み時間 | codeLoadingTime | テーブル3列目 |
| 4 | Call Activate | activate呼び出し時間 | activateCallTime | テーブル4列目 |
| 5 | Finish Activate | activate完了時間 | activateResolvedTime | テーブル5列目 |
| 6 | Event | アクティベーションイベント | activationReason.activationEvent | テーブル6列目 |
| 7 | By | トリガー元 | activationReason.extensionId.value | テーブル7列目 |

### Terminal Stats部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Name | マーク名 | perf.name (code/terminal/*) | テーブル1列目 |
| 2 | Timestamp | タイムスタンプ | perf.startTime | テーブル2列目 |
| 3 | Delta | 前マークからの差分 | 計算値 | テーブル3列目 |
| 4 | Total | 累計時間 | 計算値 | テーブル4列目 |

### Workbench Contributions部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Starting Phase | Starting Phaseのコントリビューション数と時間 | Registry.timings.Starting | `* Total (LifecyclePhase.Starting): {count} ({time}ms)` |
| 2 | Ready Phase | Ready Phaseのコントリビューション数と時間 | Registry.timings.Ready | `* Total (LifecyclePhase.Ready): {count} ({time}ms)` |

### Raw Perf Marks部

各プロセス（main, renderer等）ごとにタブ区切り形式で出力。

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Name | マーク名 | perf.name | タブ区切り |
| 2 | Timestamp | タイムスタンプ | perf.startTime | タブ区切り |
| 3 | Delta | 前マークからの差分 | 計算値 | タブ区切り |
| 4 | Total | 累計時間 | 計算値 | タブ区切り |

### Resource Timing Stats部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Name | リソース名 | performance.getEntriesByType('resource').name | テーブル1列目 |
| 2 | Duration | 読み込み時間 | entry.duration | テーブル2列目 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| timerService.whenReady() | タイマーサービス準備完了 | Yes |
| lifecycleService.when(LifecyclePhase.Eventually) | ライフサイクル到達 | Yes |
| extensionService.whenInstalledExtensionsRegistered() | 拡張機能登録完了 | Yes |
| terminalService.whenConnected | ターミナル接続完了（非Web時） | Conditional |

### ソート順

| セクション | 項目 | 昇順/降順 |
|---------|------|---------|
| Extension Activation Stats | Eager優先、その後ID順 | Eager: desc, ID: asc |
| Raw Perf Marks | Timestamp | 昇順 |
| Resource Timing Stats | Duration | N/A（取得順） |

### 改ページ条件

N/A（エディタ内表示のため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | メモリ内データを直接取得 | - |

### データ取得元詳細

#### timerService.startupMetrics

| 参照項目 | 帳票項目との対応 | 取得方法 | 備考 |
|---------|----------------|---------|------|
| platform | OS | ITimerService | OS種別 |
| release | OS | ITimerService | OSリリース |
| cpus | CPUs | ITimerService | CPU情報オブジェクト |
| totalmem | Memory (System) | ITimerService | 総メモリ(bytes) |
| freemem | Memory (System) | ITimerService | 空きメモリ(bytes) |
| meminfo | Memory (Process) | ITimerService | プロセスメモリ情報 |
| isVMLikelyhood | VM判定 | ITimerService | VM確率(%) |
| initialStartup | Initial Startup | ITimerService | 初回起動フラグ |
| windowCount | Other Windows | ITimerService | ウィンドウ数 |
| hasAccessibilitySupport | Screen Reader | ITimerService | アクセシビリティ |
| emptyWorkbench | Empty Workspace | ITimerService | 空ワークスペース |
| timers.* | Performance Marks | ITimerService | 各種タイマー値 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Memory (System) GB | totalmem / (1024^3) | 小数点2桁 | GBに変換 |
| Memory (System) free GB | freemem / (1024^3) | 小数点2桁 | GBに変換 |
| Memory (Process) MB | workingSetSize / 1024 | 小数点2桁 | MBに変換 |
| Delta | currentStartTime - previousStartTime | 整数 | 前マークとの差分 |
| Total | 累積Delta | 整数 | 累計時間 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[PerfviewContrib.getEditorInput]
    B --> C[PerfviewInput作成]
    C --> D[TextResourceEditorInput継承]
    D --> E[provideTextContent呼び出し]
    E --> F{サービス準備完了?}
    F -->|No| G[Loading...表示]
    F -->|Yes| H[_updateModel実行]
    H --> I[MarkdownBuilder初期化]
    I --> J[_addSummary]
    J --> K[_addSummaryTable]
    K --> L[_addExtensionsTable]
    L --> M[_addPerfMarksTable Terminal]
    M --> N[_addWorkbenchContributionsPerfMarksTable]
    N --> O[_addRawPerfMarks]
    O --> P[_addResourceTimingStats]
    P --> Q[model.setValue]
    Q --> R[エディタに表示]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| サービス未準備 | 起動直後でサービス未初期化 | "Loading..." | 準備完了まで待機 |
| データなし | メトリクスが取得できない | 該当セクション非表示 | - |
| リソースタイミング無し | performance APIが空 | セクション非表示 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 拡張機能数: 0-200件程度 |
| 目標出力時間 | 1秒以内（データ収集後） |
| 同時出力数上限 | 1件（単一エディタ） |

## セキュリティ考慮事項

- パフォーマンスデータは機密情報を含まない
- ファイルパスが一部含まれる可能性があるが、診断目的のため許容
- 外部送信は行わず、ローカル表示のみ

## 備考

- レポートは動的に更新される（拡張機能状態変更時）
- URI scheme `perf` で識別される仮想ドキュメント
- Word Wrapは自動的にOffに設定される

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

パフォーマンスメトリクスのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | timerService.ts | `src/vs/workbench/services/timer/browser/timerService.ts` | IStartupMetrics interfaceでメトリクス構造を確認 |

**読解のコツ**: ITimerServiceのstartupMetricsプロパティがすべてのパフォーマンスデータの入り口。

#### Step 2: エントリーポイントを理解する

レポート生成の起点を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | perfviewEditor.ts | `src/vs/workbench/contrib/performance/browser/perfviewEditor.ts` | PerfviewContribクラス（行35-64）がエントリーポイント |
| 2-2 | perfviewEditor.ts | `src/vs/workbench/contrib/performance/browser/perfviewEditor.ts` | PerfviewInput（行66-100）がエディタ入力を定義 |

**主要処理フロー**:
1. **行43**: _inputUri定義（`perf:Startup Performance`）
2. **行50**: PerfModelContentProviderの登録
3. **行57-63**: getInputUri/getEditorInputでエディタ入力を提供

#### Step 3: コンテンツ生成を理解する

Markdownコンテンツの生成ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | perfviewEditor.ts | `src/vs/workbench/contrib/performance/browser/perfviewEditor.ts` | PerfModelContentProvider（行102-320）がコンテンツ生成の中核 |

**主要処理フロー**:
- **行119-135**: provideTextContent()でモデル作成・更新
- **行137-166**: _updateModel()で各セクションを組み立て
- **行169-188**: _addSummary()でSystem Info生成
- **行190-227**: _addSummaryTable()でPerformance Marks生成
- **行229-254**: _addExtensionsTable()で拡張機能統計生成
- **行256-273**: _addPerfMarksTable()で汎用マークテーブル生成
- **行275-290**: _addWorkbenchContributionsPerfMarksTable()
- **行292-308**: _addRawPerfMarks()で生マーク出力
- **行310-319**: _addResourceTimingStats()でリソース統計

#### Step 4: MarkdownBuilderを理解する

Markdown組み立てユーティリティを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | perfviewEditor.ts | `src/vs/workbench/contrib/performance/browser/perfviewEditor.ts` | MarkdownBuilder（行322-380）でMarkdown生成 |

**主要メソッド**:
- **行326-329**: heading()で見出し生成
- **行336-338**: li()でリスト項目生成
- **行340-343**: table()でテーブル生成
- **行345-378**: toMarkdownTable()でテーブルフォーマット

### プログラム呼び出し階層図

```
Developer: Startup Performance コマンド
    │
    ├─ PerfviewContrib.getEditorInput()
    │      └─ new PerfviewInput()
    │
    └─ TextResourceEditorInput.open()
           │
           └─ textModelService.createModelReference()
                  │
                  └─ PerfModelContentProvider.provideTextContent()
                         │
                         ├─ _updateModel()
                         │      │
                         │      ├─ Promise.all([timerService, lifecycle, extension, terminal])
                         │      │
                         │      ├─ MarkdownBuilder.new()
                         │      │
                         │      ├─ _addSummary(md)
                         │      ├─ _addSummaryTable(md)
                         │      ├─ _addExtensionsTable(md)
                         │      ├─ _addPerfMarksTable('Terminal Stats', md, marks)
                         │      ├─ _addWorkbenchContributionsPerfMarksTable(md)
                         │      ├─ _addRawPerfMarks(md)
                         │      └─ _addResourceTimingStats(md)
                         │
                         └─ model.setValue(md.value)
```

### データフロー図

```
[入力]                    [処理]                           [出力]

ITimerService       ┌─────────────────────┐
  .startupMetrics ──▶│                     │
                    │ PerfModelContent    │
IExtensionService  │    Provider          │
  .getExtensions   │                     │
  Status() ─────────▶│ _addSummary()       │──────▶ ## System Info
                    │ _addSummaryTable()  │──────▶ ## Performance Marks
Registry.timings ───▶│ _addExtensionsTable()│─────▶ ## Extension Activation
                    │ _addPerfMarksTable()│──────▶ ## Terminal Stats
performance API ────▶│ _addRawPerfMarks()  │──────▶ ## Raw Perf Marks
                    │ _addResourceTiming()|──────▶ ## Resource Timing
                    └─────────────────────┘
                             │
                             ▼
                      model.setValue()
                             │
                             ▼
                       Editor Display
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| perfviewEditor.ts | `src/vs/workbench/contrib/performance/browser/perfviewEditor.ts` | ソース | メインロジック |
| timerService.ts | `src/vs/workbench/services/timer/browser/timerService.ts` | ソース | タイマーサービス |
| performance.ts | `src/vs/base/common/performance.ts` | ソース | パフォーマンスマークAPI |
| lifecycle.ts | `src/vs/workbench/services/lifecycle/common/lifecycle.ts` | ソース | ライフサイクルサービス |
| extensions.ts | `src/vs/workbench/services/extensions/common/extensions.ts` | ソース | 拡張機能サービス |
| contributions.ts | `src/vs/workbench/common/contributions.ts` | ソース | Workbenchコントリビューション |
