ネイティブコード生成

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

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

1 ネイティブコード生成は、サーバーサイドスクリプトおよびAndroidデバイス上のクライアントサイドスクリプトのみサポートされています。将来的には、より多くのデバイスがサポートされる可能性があります。

ネイティブコード生成を有効にする

Scriptのネイティブコード生成を有効にするには、--!nativeコメントを先頭に追加します:²

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

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

また、@native属性を追加することで、個々の関数に対してネイティブコード生成を有効にすることもできます。

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

ベストプラクティス

以下のヒントは、ネイティブコード生成から最大限の利益を得るのに役立ちます。

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

  • スクリプトの関数のみがネイティブにコンパイルされます。トップ外部スコープ内のコードは通常一度だけ実行され、多くの回数呼び出される関数ほどの利益は得られません。特に、毎フレーム呼び出される関数はそうです。

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

  • すべてのスクリプトに--!nativeコメントを配置して、いくつかのスクリプトがより速く実行されるかもしれないという誘惑に駆られるかもしれませんが、ネイティブコード生成にはいくつかの欠点があります:

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

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

避けるべきコード

ネイティブコード生成が有効であっても、すべての機能は同じように動作しますが、一部はネイティブで実行されず、最適化の解除や解釈実行へのフォールバックを引き起こす可能性があります。これには以下が含まれます:

  • 非推奨のgetfenv()/setfenv()呼び出しの使用。
  • 非数値引数を持つmath.asin()のようなさまざまなLuau組み込み関数の使用。
  • 型付き関数に不適切な型のパラメータを渡すこと。たとえば、function foo(arg: string)と宣言されたfooをfoo(true)で呼び出すこと。常に正しい型注釈を使用することを忘れないでください。

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

型注釈を使用する

ネイティブコード生成は、特定の変数に対して最も可能性の高い型を推測し、コードパスを最適化しようとします。たとえば、a + bは数値で行われると仮定されているか、t.Xでテーブルにアクセスされると仮定されています。しかし、演算子のオーバーロードにより、aとbはテーブルまたは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は、米国並びにその他の国における登録商標および非登録商標です。