Skip to content

perf: remove unnecessary return await and cache import maps in denops/dpp#37

Merged
Shougo merged 3 commits intomainfrom
copilot/remove-unnecessary-return-await
Mar 24, 2026
Merged

perf: remove unnecessary return await and cache import maps in denops/dpp#37
Shougo merged 3 commits intomainfrom
copilot/remove-unnecessary-return-await

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 24, 2026

Two small performance improvements to reduce microtask overhead and redundant I/O on repeated plugin loads.

Remove unnecessary return await

In dpp.ts and app.ts, several async methods simply delegate to another async function and return its result directly — outside of any try/catch — making await redundant.

Affected: DppImpl.extAction/getExt/getProtocols, the checkIf inner function (dpp.ts), and the dispatcher's extAction/getExt/getProtocols (app.ts).

// before
async getProtocols(...): Promise<...> {
  return await getProtocols(denops, this.#loader, options);
}

// after
async getProtocols(...): Promise<...> {
  return getProtocols(denops, this.#loader, options);
}

Cache import maps and ImportMapImporter (utils.ts)

tryLoadImportMap previously scanned and read import map files on every call; importPlugin created a new ImportMapImporter instance each time. Added two module-scope Maps keyed by parent directory so both the I/O and instance allocation happen at most once per directory per process lifetime.

const importMapCache = new Map<string, ImportMap | null>();
const importerCache = new Map<string, ImportMapImporter>();

tryLoadImportMap checks importMapCache before touching disk, storing null for directories with no import map. importPlugin reuses the cached ImportMapImporter rather than constructing a new one. External API is unchanged.

Note: import map changes made while the process is running will not be picked up — acceptable for typical Deno/denops usage where the process lifetime matches the editor session.

Original prompt

目的

  • パフォーマンス改善と軽微な最適化のため、denops/dpp の実装に対して安全に適用できる変更を行い、PR を作成します。対象は「不要な return await の削除」と「import-map 読み込みのプロセス内キャッシュ化(ImportMapImporter の再利用)」です。既にテストが追加されているため、小さなリファクタは安全に検証できます。

変更内容(要約)

  1. 不要な return await の削除

    • 理由: return await foo() は通常不要で、余計な microtask とわずかなオーバーヘッドを発生させます。try/catch 内で例外スタックを保持する必要がある箇所を除き、return foo() に置換します。
    • 対象ファイル(主な例):
      • denops/dpp/dpp.ts
        • extAction, getExt, getProtocols 等の単純に別関数の戻り値を返している非同期関数
      • denops/dpp/app.ts
        • dispatcher の getExt, getProtocols, extAction など
    • 実装方針: 動作が try/catch 内で例外ハンドリングを行っているケースはそのままにし、単純返却の場合のみ return に変更する。テスト実行で差異を検証する。
  2. import-map / ImportMapImporter のキャッシュ化

    • 理由: 汎用の importPlugin/tryLoadImportMap は呼び出しごとに import_map.* ファイルを探索・読み込みし、ImportMapImporter を新規作成しています。プロセス内で同一ディレクトリの import map と ImportMapImporter をキャッシュして再利用することで I/O とインスタンス生成を削減します。
    • 対象ファイル: denops/dpp/utils.ts
    • 実装内容(概念):
      • モジュールスコープのキャッシュを追加:
        • importMapCache: Map<string /* dir */, ImportMap | null>
        • importerCache: Map<string /* dir */, ImportMapImporter>
      • tryLoadImportMap(path) はディレクトリをキーにしてキャッシュを参照。キャッシュ未ヒット時のみ既存の探索/読み込みを行い、結果をキャッシュに保存(存在しない場合は null を保存)
      • importPlugin(path) は tryLoadImportMap が返した importMap を使い、importerCache に ImportMapImporter があれば再利用する。存在しなければ作成してキャッシュへ保存。
    • 互換性: 外部仕様は変更しない(振る舞いは同じ)。import_map ファイルの変更がランタイムで反映されない可能性があるが、一般的な Deno + denops のユースケースではプロセス内キャッシュで十分。必要なら将来的に TTL/強制リロード API を追加する。

追加の安全対策

  • 変更は小さく分けてコミットします。
    1. return-await の削除のみのコミット
    2. import-map キャッシュ実装のコミット
  • 既存のマージ済みテストを用いて動作確認を行います。
  • PR の本文に変更理由、影響範囲、テスト手順を記載します。

テスト手順(PR レビュー向け)

  • ローカル / CI で deno test を実行: deno test -A --doc --parallel --shuffle denops/**/*.ts
  • 変更が問題なければテストは全て成功するはずです。

PR タイトル案

perf: remove unnecessary return await and cache import maps in denops/dpp

作業内容の詳細(差分の予定)

  • denops/dpp/dpp.ts

    • extAction: return await extAction(...)return extAction(...)
    • getExt: return await getExt(...)return getExt(...)
    • getProtocols: 同上
  • denops/dpp/app.ts

    • dispatcher.extAction / getExt / getProtocols 等: return await ...return ... に置換
  • denops/dpp/utils.ts

    • モジュールスコープに以下のキャッシュを追加
      • const importMapCache = new Map<string, ImportMap | null>();
      • const importerCache = new Map<string, ImportMapImporter>();
    • tryLoadImportMap(script: string)
      • 先にキャッシュを参照し、キャッシュヒットなら即時返却
      • 未ヒットなら既存ロジックで探索・loadImportMap を試行、結果をキャッシュ
    • importPlugin(path: string)
      • tryLoadImportMap の返り値を得る
      • importMap がある場合は importerCache を参照し、存在すれば importer.import(url) を呼ぶ。無ければ新規作成してキャッシュに保存し import
      • importMap が無い場合は従来通り import(${url}#${suffix})

注意点

  • キャッシュはプロセス内キャッシュです。import_map のランタイム更新を即座に反映する必要があるユースケースでは追加対策が必要です。
  • return-await の除去は、try/catch によりスタックトレースの取り扱いが変わるケースを確認してから行います。今回の対象は単純ラップの関数のみを想定しています。

PR の作成先

  • リポジトリ: Shougo/dpp.vim
  • ベースブランチ: main

お願い(自動化)

この PR を作成して、変更の差分と PR URL を返してください。テストが自動で実行できるように、必要なら CI workflow の追加は別 PR を提案します。

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: @Shougo/dpp.vim こちらを改善する作業をしてください

Assistant: I'll run a quick repository audit on Shougo/dpp.vim to identify concrete improvement areas (code, docs, CI, tests, packaging, and common issues). I'll fetch repository metadata and file list now.

Assistant: 直接の推奨:まずリポジトリを監査して改善優先度を決めました。低摩擦で価値が高い順に着手できます — どれを私に実装(PR作成)させましょうか?(実装してPRを作る場合は「PR作成して」と一言ください。すぐに作業します。)

何をやったか(私の作業)

  • GitHubのリポジトリメタとルートファイルを確認しました(README.md, Makefile, deno.jsonc, pkg.json, autoload/, denops/, lua/, doc/ 等)。
  • 言語は TypeScript(メタ情報)ですが、Denops/Neovimプラグイン固有のファイル群があり、Deno・Lua・Vimscript混在の構成と想定されます。
  • CIワークフロー情報は利用できるAPIで一覧できなかったため、リポジトリにCIが無いか限定的である可能性を想定しました。

主要な改善候補(優先度付き)

  1. CIの追加(高優先、低摩擦)

    • 目的:PRやコミットで基本チェックを自動化(フォーマット・型チェック・テスト)。
    • 具体案:GitHub Actionsワークフローを追加
      • deno fmt / deno lint / deno test(deno.jsonc があるため)
      • TypeScript 型チェック(必要なら deno check)
      • Lua の lint(luacheck)や lua-format をオプションで実行
      • ワークフロー名: ci.yml(.github/workflows/ci.yml)
    • 効果:品質の自動保証、外部貢献者のハードル低下。
  2. テスト整備(高優先)

    • 目的:プラグインの振る舞いを担保。
    • 具体案:denops 向けのユニット/統合テスト(deno test)追加、可能なら CI での neovim インスタンスでの統合テスト(neovim-headless)。
    • 効果:リファクタや機能追加が安全に行える。
  3. ドキュメント改善(高→中優先)

    • 目的:導入・使い方・開発ガイドを明確化。
    • 具体案:
      • README に「インストール方法」「基本使い方(例)」「設定項目」「開発方法(テスト/ビルド/PR手順)」を分かりやすく追加。
      • CONTRIBUTING.md と ISSUE/PR テンプレートを追加(.github/ 配下)。
    • 効果:外部コントリビューション増、ユーザ降りる障壁の低下。
  4. Lint / Formatter の導入(中優先)

    • 目的:一貫したコードスタイル。
    • 具体案:deno fmt をワークフローに組み込み、TypeScript/Lua の lint/format 設定(eslintrcは不要で deno 標準)。Makefile に make fmt, make lint 追加。
    • 効果:コードの可読性向上。
  5. パッケージング & 配布(中優先)

    • 目的:インストール方法を安定化(vim-plug / packer / lazy の例)。
    • 具体案:README に複数プラグインマネージャー向けのインストール例、GitHub Release を使ったバージョニング方針を追加。
    • 効果:利用者増、信頼性向上。
  6. リファクタと型の強化(低→中優先)

    • 目的:TypeScript/deno 部分の型安全性向上や非同期処理の整理。
    • 具体案:deno check を CI に入れて型エラーを防ぐ、必要ならtsconfigの整備(denoなら不要)。
    • 効果:バグ減、保守性向上。
  7. テレメトリ・例外ハンドリング強化(低優先)

    • 目的:エラー情報の一貫したログ出力、ユーザへ親切なエラーメッセー...

This pull request was created from Copilot chat.


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Copilot AI changed the title [WIP] Fix unnecessary return await in denops/dpp implementation perf: remove unnecessary return await and cache import maps in denops/dpp Mar 24, 2026
Copilot AI requested a review from Shougo March 24, 2026 00:20
@Shougo Shougo marked this pull request as ready for review March 24, 2026 00:28
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