Skip to content

perf: reduce CPU usage during rapid typing#174

Merged
Shougo merged 2 commits intomainfrom
copilot/investigate-cpu-usage-issue
Apr 27, 2026
Merged

perf: reduce CPU usage during rapid typing#174
Shougo merged 2 commits intomainfrom
copilot/investigate-cpu-usage-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 25, 2026

Summary

素早いキー入力時の CPU 使用率増加に対して、前回の調査結果から特定された5つのホットスポットを修正します。

Changes

改善A — onEvent() を skip 判定の後へ移動 (denops/ddc/app.ts)

TextChangedI が連続して発火し isNegligibletrue になるケース(入力が変化していない冗長なイベント)でも、従来は全ソース・全フィルターの onEvent() を呼んでいました。skip チェックの 後に onEvent() / cbContext.revoke() を移動することで、この無駄な呼び出しを排除します。

cbContext.revoke() も skip ガードの後へ移動し(意味的に正しい位置)、コメントを追加しました。

改善B — オプション変更時のみ #validate() を実行 (denops/ddc/context.ts)

createContext() は全キー入力ごとに DdcOptions の全キーをループして検証していました。#needsValidation フラグを追加し、set* / patch* メソッド呼び出し後のみ検証が走るようにします。ランタイム中はオプションが頻繁に変わらないため、ほぼ定常的に検証をスキップできます。

改善C — TextEncoder/TextDecoder をモジュールレベルシングルトンに (denops/ddc/ddc.ts)

byteposToCharpos()charposToBytepos() は呼び出しのたびに new TextEncoder() / new TextDecoder() を生成していました。モジュールスコープの定数に変更することで GC 圧力を削減します。

改善G — cacheTimeout の時刻ソースを修正 (denops/ddc/ddc.ts)

Date#getSeconds() は 0–59 の値を返し、分をまたぐとリセットされます。そのため分境界でキャッシュが期限切れにならないバグがありました。Math.floor(Date.now() / 1000) (エポックからの秒数)に変更して単調増加する値を使用します。単位は従来通り「秒」のまま維持するため、既存の cacheTimeout 設定値は変更不要です。

改善E — getFilter() の重複呼び出しを排除 (denops/ddc/ext.ts)

runMatchersConcurrently()parallelSafe チェックのためにフィルターを一度解決した後、callFilters() に元の UserFilter 名を渡していたため、各チャンクごとに再度 getFilter() が呼ばれていました。解決済みタプルを受け取る callResolvedFilters() ヘルパーを導入し、全ブランチ・全チャンクで再利用します。missing filter のハンドリングは型述語フィルターで行い、非 null アサーション (!) を除去しました。

セーフティチェック

  • 改善A: InsertLeave / BufEnter 等は isNegligiblefalse になるため onEvent() は引き続き呼ばれます。TextChangedI の skip=true ケース(同一 input の連続イベント)で source.onEvent がスキップされますが、このケースでソースが副作用を期待することは通常ありません。
  • 改善B: set* / patch* で必ずフラグが立つため、設定変更直後の最初の補完サイクルでは検証が実行されます。
  • 改善G: cacheTimeout の単位(秒)は変わらないため後方互換性あり。

Copilot AI and others added 2 commits April 25, 2026 10:39
- app.ts: skip onEvent() call when event is negligible (改善A)
  Move source/filter onEvent dispatch after the skip guard so it is
  not executed for redundant TextChangedI events where input has not
  actually changed.  cbContext.revoke() is also moved to the correct
  position (after the skip guard, before onEvent).

- context.ts: validate options only on mutation (改善B)
  Add #needsValidation flag to ContextBuilderImpl.  All set*/patch*
  methods set the flag; createContext runs #validate() only when the
  flag is true, then clears it.  This avoids iterating every option
  key on every keystroke.

- ddc.ts: TextEncoder/TextDecoder module-level singletons (改善C)
  byteposToCharpos() and charposToBytepos() previously allocated new
  TextEncoder/TextDecoder instances on every call.  Reuse a single
  pair of instances at module scope.

- ddc.ts: fix cacheTimeout time source (改善G)
  Date#getSeconds() returns 0-59 and wraps, causing the minute
  boundary to reset the comparison and prevent cache expiry.  Switch
  to Math.floor(Date.now()/1000) for a monotonically growing
  seconds-since-epoch value.

- ext.ts: eliminate duplicate getFilter() calls (改善E)
  runMatchersConcurrently() resolved filters once for the parallelSafe
  check but then passed the original UserFilter names back to
  callFilters(), which resolved them again.  Refactor to a
  callResolvedFilters() helper that operates on pre-resolved tuples
  and reuse those across all branches and chunks.

Agent-Logs-Url: https://github.com/Shougo/ddc.vim/sessions/b543f2b0-5b9e-4f7c-84ce-a7e4942a8f2c

Co-authored-by: Shougo <41495+Shougo@users.noreply.github.com>
- app.ts: add comment explaining why cbContext.revoke() sits after the
  skip guard
- ext.ts: replace non-null assertion (!) with a type-predicate filter
  when narrowing resolved matchers, eliminating the unchecked cast

Agent-Logs-Url: https://github.com/Shougo/ddc.vim/sessions/b543f2b0-5b9e-4f7c-84ce-a7e4942a8f2c

Co-authored-by: Shougo <41495+Shougo@users.noreply.github.com>
Copilot AI requested a review from Shougo April 25, 2026 10:42
@Shougo Shougo marked this pull request as ready for review April 25, 2026 11:00
@Shougo Shougo merged commit 9f5a7e9 into main Apr 27, 2026
3 checks passed
@Shougo Shougo deleted the copilot/investigate-cpu-usage-issue branch April 27, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants