luau-performance について
luau-performanceは、Luauの実行性能を最適化する開発者向けのスキルです。プロファイリングでボトルネックを確認し、反復処理や割り当てを減らしながら、保守性も考慮します。
主な機能
- 01実行時のボトルネックを測定
- 02割り当てとGC負荷の削減
- 03テーブルと反復方法の選択
- 04組み込み関数とコンパイラーの高速経路を維持
- 05プロファイルと実行時資料の参照
活用シーン
- 01測定済みの遅いLuau関数の調査
- 02頻繁に実行するコードの割り当て削減
- 03ホットパスのテーブル操作と反復の調整
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ luumenlabs/ luau-skills --skill luau-performanceインストール後、Claude Code で/luau-performanceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/library-performance-sensitive-patterns.mdluau-performance-guide.mdprofiling-guide.mdruntime-and-compiler-optimization-notes.mdsandbox-constraints-relevant-to-runtime-behavior.md詳細
luau-performance
使用する場面
主なタスクが Luau の実行時コストに関する場合は、このスキルを使用します。
- 実装の詳細を変更する前に、コードをプロファイリングして実際のホットスポットを見つける。
- 繰り返し実行される処理で、割り当ての頻発、GC への負荷、クロージャーの生成を減らす。
- テーブルの構築、検索、追加、反復処理をより高速に行うパターンを選ぶ。
- 組み込み関数の呼び出し、メソッド呼び出し、インポートで、Luau の高速パスが機能するようにコードを記述する。
- コンパイラーとランタイムの最適化が、ホット関数に与える影響を説明する。
- 読みやすさと保守性のバランスを取りながら、ホットパスとして確認された処理を調整する。
- サンドボックスや環境の動作が Luau の実行を変化させたり、コードを最適化対象から外したりする場合に限り、その影響を考慮する。
主なタスクが次の内容に関する場合は、このスキルを使用しないでください。
- Luau の構文、制御フロー、テーブル、メタテーブルを基礎から教える。
- 複雑な型システムの抽象化、アナライザーの動作、高度な型ユーティリティを設計する。
- Roblox 固有のレプリケーション、ストリーミング、レンダリング、ネットワーキング、物理演算、その他のエンジン性能パターンを扱う。
判断ルール
- まず測定してください。コードが単純でない場合は、最適化について主張する前にプロファイリングまたはベンチマークを実施します。
- バイトコードレベルの詳細をマイクロ最適化する前に、アルゴリズムのコストを改善します。
- ホットパスで、繰り返しの処理、繰り返しの割り当て、繰り返しの動的ディスパッチをなくす変更を優先します。
- 性能が重要なモジュールは、純粋な環境で動作させます。速度が重要な場合は、
getfenv、setfenv、loadstringを避けます。 - ホットコードでは、安定したテーブルの形状、直接的なフィールドアクセス、組み込み関数の直接呼び出し、シンプルな呼び出しグラフを優先します。
- 環境固有のコンパイル機能は、測定によって効果が見込まれ、かつ実行環境が実際にサポートしている場合にのみ使用します。
- タスクが言語の基礎学習に移った場合は、
luau-coreを使用します。 - タスクの主題が型、推論、注釈に移った場合は、
luau-typesを使用します。 - タスクが Luau の実行動作ではなく Roblox エンジンのアーキテクチャに依存する場合は、適切な
roblox/*スキルに引き継ぎます。 - 依頼に性能改善と対象外のトピックが混在する場合は、Luau の実行時に関する部分のみを回答し、それ以外は除外します。
手順
- まずワークロードを定義します。
- 頻繁に実行される処理は何か
- 頻繁に割り当てが発生する処理は何か
- クリティカルパス上にある処理は何か
- 最も重要な指標は何か:実時間、フレーム予算、メモリの churn
- 書き換える前にプロファイリングします。サンプリングや環境のツールを使い、実際に実行時間の大部分を占めている関数を特定します。
- 検証済みのボトルネックのうち、最も大きなものから最適化します。実行頻度の低いコードにマイクロ最適化を散りばめないでください。
- 繰り返し実行されるパスでの割り当て負荷を減らします。
- 毎回テーブルを作り直さないでください。
- 必要がない限り、ループ内で新しいクロージャを作成しないでください。
- テーブルや接続を必要以上に長く保持しないでください。
- ランタイムに適したテーブルを構成します。
- 既知のフィールドがすべて揃ったオブジェクトのようなテーブルを作成するには、テーブルリテラルを使います。
- 呼び出し間でオブジェクトのレイアウトを統一します。
- 容量が既知の配列のようなテーブルに限り、
table.createを使います。
- 意図を持って反復方法を選びます。
- 通常のテーブル走査には、汎用イテレーション
for k, v in t doを使います。 - 最初の
nilで反復を停止する動作が必要な場合に限り、ipairsを使います。 - インデックス自体が必要な場合や、連続書き込みがアルゴリズムの一部である場合は、数値ループを使います。
- 通常のテーブル走査には、汎用イテレーション
- 組み込み関数の高速パスを明確に保ちます。
math.max(x, y)やstring.byte(s, 1)のように、組み込み関数を直接呼び出します。- ホットな組み込み関数の呼び出しを、不要な間接参照で隠さないでください。
- fastcall の動作が呼び出し形式に依存する場合は、メソッド形式より組み込み関数形式を優先します。
- コンパイラーに適した呼び出し箇所を保ちます。
- ホットなヘルパーには
local functionを優先します。 - キャプチャされた値を不必要に変更しないでください。
- インライン化の機会が増える場合は、小さなヘルパーをモジュール内に置きます。
- ホットなヘルパーには
- ホットなコードでメタテーブルの使用コストを抑えます。
- データはオブジェクト自体に格納します。
__indexはテーブルを直接参照するようにします。- クリティカルパスでは、
__index関数や深い検索チェーンを避けます。
- 環境機能をパフォーマンス上の制約として扱います。
getfenv、setfenv、loadstringは、インポートや組み込み関数の高速処理を最適化解除する場合があります。- 環境によっては、デバッグやブレークポイントが観測されるランタイムの動作を変えることがあります。
- ネイティブコンパイルがサポートされている場合は、対象を選んで適用し、測定します。
- 実用性を重視します。理論上はより高速な書き換えがあっても、測定可能なコストを取り除ける最もシンプルな変更を優先します。
リファレンスの使用
references/luau-performance-guide.mdを開き、テーブルアクセス、インポート、メソッド呼び出し、反復処理、割り当てを意識したテーブル構築など、Luau の主要な高速パスのモデルを確認します。references/profiling-guide.mdを開き、プロファイラーのワークフロー、フレームグラフの解釈、関数への帰属を明確にするための名前付け、環境固有のプロファイリングに関する注意事項を確認します。references/runtime-and-compiler-optimization-notes.mdを開き、コンパイラーの制限、インライン化、定数畳み込み、アップバリュー、クロージャーのキャッシュ、対象を選んだネイティブコンパイルに関する指針を確認します。references/library-performance-sensitive-patterns.mdを開き、math、string、table、反復ヘルパー、配列指向 API に関する実用的な選択肢を確認します。references/sandbox-constraints-relevant-to-runtime-behavior.mdを開き、ランタイムの最適化を無効化または弱める環境ルールを確認します。- タスクが明らかに別のスキルの範囲に及ばない限り、他のスキルリファレンスは開かないでください。
チェックリスト
- 主張するホットスポットについて、測定計画またはプロファイラーの結果がある。
- 提案する変更が、効果を出せるだけの頻度で実行されるパスを対象にしている。
- 構文のマイクロチューニングより先に、アルゴリズム上のコストを検討している。
- 繰り返される処理の割り当て churn を減らしている。
- テーブルの形状と反復方法がデータのパターンに合っている。
- 可能な場合、組み込み関数の呼び出しを十分に直接的に保ち、高速パスを維持している。
getfenv、setfenv、loadstringなど、最適化を解除する機能をホットなモジュールで避けている。- 環境固有のコンパイル機能は、推測ではなく測定に基づいて採用している。
- 指針が Luau の実行動作の範囲内に収まっており、Roblox エンジンのパフォーマンスに関する話題を避けている。
よくある間違い
- 「ホットに見える」という理由で、測定せずにコードを最適化する。
- 配列ではなく辞書に
table.createを使う。 pairsやipairsは汎用イテレーションより自動的に速いと思い込む。- Luau がメソッド呼び出しをすでに適切に最適化している場合でも、
obj:Method()をキャッシュしたメソッドのローカル変数に書き換える。 - ホットパスで、組み込み関数の呼び出しをラッパーや間接ディスパッチの背後に隠す。
- オブジェクトテーブルのキーを大きく変動させながら、フィールド検索のキャッシュが効果を保つと期待する。
- 読み取りにのみ
getfenvを使い、最適化コストは発生しないと思い込む。 - メモリ、起動時間、実際の実行時の効果を測定せずに、ネイティブコンパイルのディレクティブをあちこちに追加する。
例
配列を事前割り当てして順番に埋める
local function buildSquares(count)
local result = table.create(count)
for i = 1, count do
result[i] = i * i
end
return result
end
ホットコードでは組み込み関数を直接使う
local function clamp01(x)
return math.min(math.max(x, 0), 1)
end
オブジェクトのレイアウトを安定させ、__index を直接使う
local Counter = {}
Counter.__index = Counter
function Counter.new(step)
return setmetatable({
value = 0,
step = step,
}, Counter)
end
function Counter:advance()
self.value += self.step
return self.value
end
パフォーマンスが重要なモジュールでは環境の最適化を妨げない
local function magnitude2(x, y)
return math.sqrt(x * x + y * y)
end
return magnitude2
コメント
Markdown 対応