ネイティブコード生成

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

Luauのネイティブコード生成をサポートすることで、ゲーム内のサーバーサイドスクリプトは、Luau VMが操作する通常のバイトコードではなく、CPUが実行するマシンコード命令に直接コンパイルされます。この機能は、特に重いLuauライブラリやRoblox API呼び出しを多く使用せずに、多くの数値計算を行うスクリプトの実行速度を向上させるために使用できます。

ネイティブコード生成の有効化

Scriptのネイティブコード生成を有効化するには、最上部に--!nativeコメントを追加します:¹


--!native
print("ネイティブコードからこんにちは!")

これにより、スクリプト内のすべての関数と、利益が見込まれる場合はトップレベルスコープに対してネイティブコード生成が有効化されます。追加の変更は必要ありません; ネイティブに実行されるスクリプトの動作は以前とまったく同じで、パフォーマンスだけが異なります。Luau言語のすべての機能とすべてのRoblox APIは引き続きサポートされます。

また、個々の関数に対してネイティブコード生成を有効化するには、@native属性を追加します:


@native
local function f(x)
return (x + 1)
end
1 将来的には、利益が見込まれる場合、いくつかのスクリプトは自動的にネイティブに実行されるかもしれませんが、現在は手動で配置された--!nativeコメントが必要です。

ベストプラクティス

次のヒントは、ネイティブコード生成の利点を最大限に引き出すのに役立ちます:

  • 大量の計算をLuau内部で直接行うスクリプト内でこの機能を有効にするのが最も良いです。テーブルに対する多くの数学的操作、特にbufferタイプがある場合、そのスクリプトは良い候補になるかもしれません。

  • スクリプトの関数のみがネイティブにコンパイルされます。外側のスコープのコードはほとんどの場合1回だけ実行され、多くの回数呼び出される関数ほど恩恵を受けません。

  • ネイティブコンパイル有無でスクリプトや関数がかかる時間を測定して、使用するのが最適なタイミングを判断することをお勧めします。スクリプトプロファイラーツールは、情報に基づいた決定を下すために関数のパフォーマンスを測定できます。

  • すべてのスクリプトに--!nativeコメントを配置するのは魅力的かもしれませんが、ネイティブコード生成にはいくつかの欠点があります:

    • コードコンパイル時間が必要で、サーバーの起動時間が増加する可能性があります。
    • ネイティブにコンパイルされたコードを保存するために追加のメモリが占有されます。
    • ゲーム内で許可されるネイティブにコンパイルされたコードの合計量には制限があります。

これらの問題は、@native属性を賢く使用することで対処できます。

避けるべきコード

ネイティブコード生成が有効であっても、すべての機能が同じように動作しますが、いくつかはネイティブに実行されず、最適化が非効率になるか、解釈された実行にフォールバックする可能性があります。これには以下が含まれます:

  • 非推奨のgetfenv()/setfenv()呼び出しの使用。
  • 数値引数でないmath.asin()などのさまざまなLuau組み込み関数の使用。
  • 型の異なるパラメータを型付き関数に渡すこと、たとえばfunction foo(arg: string)と宣言された関数にfoo(true)と呼び出すこと。常に正しい型アノテーションを使用することを忘れないでください。

スクリプトプロファイラーを使用することで、通常のバージョンの関数とネイティブにコンパイルされたものとの実行時間を比較できます。--!nativeスクリプト内または@nativeでマークされた関数がネイティブで実行されていない場合、上記のリストの1つ以上の要因が最適化を無効にしている可能性があります。

型アノテーションを使用する

ネイティブコード生成は、与えられた変数に対して最も可能性の高い型を推測して、コードパスを最適化しようとします。たとえば、a + bは数字で行われると仮定され、t.Xでテーブルにアクセスされると想定されます。しかし、演算子のオーバーロードによって、abはテーブルまたはVector3型である可能性があり、tはRobloxデータ型である可能性があります。

ネイティブコード生成は任意の型をサポートしますが、誤った予測は不要なチェックを引き起こし、コードの実行を遅くする可能性があります。

いくつかの一般的な問題を解決するために、関数引数のLuau型アノテーションがチェックされますが、特にVector3引数にアノテーションを付けることが推奨されます:


--!native
-- "v"はテーブルであると仮定されるため、テーブルチェックにより関数が遅く実行される
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- "v"はVector3として宣言されるため、ベクトル用に特化されたコードが生成される
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
end

スタジオツール

次のスタジオツールは--!nativeスクリプトおよび@native関数をサポートしています。

デバッグ

スクリプトの一般的なデバッグがサポートされていますが、ローカル/アップバリューのビューは不完全で、ネイティブに実行されているコールスタックフレームから変数が欠落している場合があります。

また、ネイティブコンパイル用に選択されたコードをデバッグする際には、ブレークポイントを配置すると、その関数のネイティブ実行が無効化されることに注意してください。

スクリプトプロファイラー

スクリプトプロファイラーでは、ネイティブに実行されている関数の横に<native>が表示されます:

スクリプトプロファイラーでフラグが付けられたネイティブ関数の例

@nativeでマークされた関数または--!nativeスクリプト内の関数が<native>アノテーションを表示しない場合、その関数はブレークポイントの配置、避けるべきコードの使用、あるいは不一致な型アノテーションのためにネイティブに実行されていない可能性があります。

Luauヒープ

Luauヒーププロファイラーでは、ネイティブ関数によって占有されたメモリがグラフ内の[native]要素として表示されます。

Luauヒーププロファイラーでフラグが付けられたネイティブメモリ使用の例

サイズ分析

すべてのネイティブコンパイルされたスクリプトはメモリを消費します。コンパイルされたコードのサイズがあらかじめ定義された制限に達すると、ネイティブコンパイルは停止し、残りのコードは非ネイティブで実行されます。これにより、ネイティブコンパイル用のスクリプトを慎重に選択することが重要です。

個々の関数やスクリプトのネイティブコードサイズを監視するには:

  1. クライアント/サーバー切替ボタンを通じてサーバービューになっていることを確認します。
  2. コマンドバーdebug.dumpcodesize()を呼び出します。

出力ウィンドウには、呼び出し時点までにネイティブにコンパイルされたスクリプトや関数の合計数、ネイティブコードが占有するメモリ、ネイティブコードのサイズ制限が表示されます。概要の後、コードサイズの降順でネイティブコンパイルされたスクリプトごとの表が表示されます。

出力ウィンドウに表示されたネイティブコードサイズの例。

各スクリプトについて、出力にはコンパイルされた関数の数とネイティブコードメモリ消費量が表示されます。その後、各関数はネイティブコードサイズの降順でリストされ、匿名関数は[anonymous]として、全体のスクリプトは[top level]として表示されます。最後の列には、ネイティブコードサイズ制限に関するパーセンテージが計算されて表示されます。関数のネイティブコードサイズは正確に報告されますが、スクリプトのメモリ消費量は最も近いページサイズに切り上げられます。

制限とトラブルシューティング

特定のCPU用にコードを命令にコンパイルすることは、追加のストレージメモリを必要とします。さらに、複雑な関数の最適化には時間がかかる場合があります。内部制限に達すると、スタジオの出力ウィンドウにエラーが報告されます:

関数'f'は行20で単一のコードブロック命令制限を超えました

このエラーは、関数内の単一のコードブロックが64K命令を超えて使用されたことを意味します。この問題は、関数を簡素化するか、個々の小さな関数に分割することによって回避できます。

関数'f'は行20で関数コードブロックの制限を超えました

このエラーは、単一の関数が32K以上の内部コードブロックを含んでいることを意味します。内部のコードブロックはスクリプト内の制御フローブロックに正確には対応していませんが、このエラーは関数内の制御フローを簡素化するか、個々の小さな関数に分割することによって回避できます。

関数'f'は行200で総モジュール命令制限を超えました

このエラーは、合計で、その関数がスクリプト全体に対して100万命令の制限に達したことを意味します。場合によっては、報告された関数自体が多数の命令を含んでいるか、あるいは制限がスクリプト内の以前の関数によって達成されている可能性があります。この問題を避けるためには、特に大きな関数を別の非ネイティブスクリプトに移動するか、他の関数に@nativeを使用することが推奨されます。また、別のスクリプトを--!nativeでマークすることもできるかもしれませんが、100万命令は多くのメモリを占有し、メモリ制限を超える可能性があります。

関数'f'は行20で内部降下失敗に遭遇しました (または)
内部エラー: ネイティブコード生成に失敗しました(アセンブリ降下)

時には、関数内にネイティブコードコンパイラーが現在処理できない複雑なコード片が含まれることがあります。このエラーを回避するためには、コード内の複雑な表現を検査してそれらを分割または簡素化し、この理由で失敗したコードの例を含むバグレポートを開くことを検討してください。

ネイティブコード生成のためのメモリアロケーション制限に達しました

このエラーは、ネイティブコードデータの全体的なメモリ制限に達したことを意味します。これを回避するためには、よりメモリを多く消費するスクリプトから--!nativeを削除して、より多くの小規模なスクリプトが制限内に収まるようにします。あるいは、大きな関数や呼び出し頻度の低い関数を別の非ネイティブモジュールに移動することを検討してください。

©2026 Roblox Corporation。Roblox(ロブロックス)、RobloxロゴおよびPowering Imaginationは、米国並びにその他の国における登録商標および非登録商標です。