Avec le support de Luau pour la génération de code natif, les scripts côté serveur de votre jeu peuvent être compilés directement en instructions de code machine que les CPU exécutent, plutôt qu'en bytecode régulier sur lequel fonctionne la VM Luau. Cette fonctionnalité peut être utilisée pour améliorer la vitesse d'exécution de certains scripts sur le serveur, en particulier ceux qui effectuent beaucoup de calculs numériques sans utiliser trop d'appels à la bibliothèque Luau ou à l'API Roblox.
Activer la génération de code natif
Pour activer la génération de code natif pour un Script, ajoutez le commentaire --!native en haut:¹
--!nativeprint("Bonjour depuis le code natif !")
Cela active la génération de code natif pour toutes les fonctions dans le script, et le scope de niveau supérieur, si cela est jugé profitable. Aucun changement supplémentaire n'est requis ; le comportement des scripts s'exécutant de manière native est exactement le même qu'auparavant et seule la performance est différente. Toutes les fonctionnalités du langage Luau et toutes les API Roblox restent prises en charge.
Alternativement, vous pouvez activer la génération de code natif pour une fonction individuelle en ajoutant l'attribut @native :
@native
local function f(x)
return (x + 1)
end
Meilleures pratiques
Les conseils suivants vous aideront à tirer le meilleur parti de la génération de code natif :
Il est préférable d'activer cette fonctionnalité dans les scripts qui effectuent beaucoup de calculs directement dans Luau. Si vous avez beaucoup d'opérations mathématiques sur des tables et en particulier des types buffer, le script pourrait être un bon candidat.
Il est recommandé de mesurer le temps qu'un script ou une fonction prend avec et sans compilation native pour juger du meilleur moment pour l'utiliser. L'outil Script Profiler peut mesurer la performance des fonctions afin de prendre des décisions éclairées.
Il peut être tentant de placer le commentaire --!native dans chaque script juste au cas où certains d'entre eux s'exécuteraient plus vite, mais la génération de code natif a quelques inconvénients :
- Le temps de compilation du code est requis, ce qui peut augmenter le temps de démarrage des serveurs.
- De la mémoire supplémentaire est occupée pour stocker le code compilé de manière native.
- Il y a une limite sur la quantité totale de code compilé de manière native autorisée dans un jeu.
Ces problèmes peuvent être traités par un usage judicieux de l'attribut @native.
Code à éviter
Bien que toutes les fonctionnalités se comportent de la même manière avec ou sans génération de code natif activée, certaines d'entre elles ne s'exécuteront pas de manière native et pourraient causer une dé-optimisation ou un retour à l'exécution interprétée. Cela inclut :
- L'utilisation de diverses fonctions intégrées de Luau comme math.asin() avec des arguments non numériques.
- Le passage de paramètres mal typés à des fonctions typées, par exemple en appelant foo(true) lorsque foo est déclaré comme function foo(arg: string). N'oubliez pas d'utiliser toujours des annotations de types correctes.
Lorsque vous utilisez le Script Profiler, vous pouvez comparer le temps pris par une version régulière de la fonction par rapport à celle compilée de manière native. Si une fonction à l'intérieur d'un script --!native ou marquée avec @native n'apparaît pas comme s'exécutant de manière native, un ou plusieurs facteurs de la liste ci-dessus peuvent déclencher une dé-optimisation.
Utiliser des annotations de type
La génération de code natif tente d'inférer le type le plus probable pour une variable donnée afin d'optimiser les chemins de code. Par exemple, on suppose que a + b est effectué sur des nombres, ou qu'une table est accessible dans t.X. Étant donné la surcharge d'opérateurs, cependant, a et b peuvent être des tables ou des types Vector3, ou t peut être un type de données Roblox.
Bien que la génération de code natif prenne en charge n'importe quel type, des erreurs de prédiction peuvent déclencher des vérifications inutiles, ce qui entraîne une exécution du code plus lente.
Pour résoudre certains problèmes courants, les annotations de type Luau sur les arguments de fonction sont vérifiées, mais il est particulièrement recommandé d'annoter les arguments Vector3 :
--!native
-- "v" est supposé être une table ; la fonction s'exécute plus lentement en raison des vérifications de table
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- "v" est déclaré comme un Vector3 ; du code spécialisé pour les vecteurs est généré
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
end
Outils de Studio
Les outils de Studio suivants sont pris en charge pour les scripts --!native et les fonctions @native.
Débogage
Le débogage général des scripts est pris en charge, mais les vues pour les locaux/upvalues peuvent être incomplètes et manquer de variables dans les cadres des call stack qui s'exécutent de manière native.
Veuillez également noter que lors du débogage du code sélectionné pour la compilation native, la mise en place de points d'arrêt désactivera l'exécution native pour ces fonctions.
Script Profiler
Dans le Script Profiler, les fonctions s'exécutant de manière native affichent <native> à côté d'elles :

Si une fonction marquée @native ou à l'intérieur d'un script --!native ne montre pas l'annotation <native>, cette fonction peut ne pas s'exécuter de manière native en raison de la mise en place de points d'arrêt, de l'utilisation de code découragé, ou d'annotations de types incompatibles.
Tas Luau
Dans le profileur Luau heap, la mémoire occupée par des fonctions natives est affichée comme des éléments [native] dans le graphique.

Analyse de la taille
Chaque script compilé de manière native consomme de la mémoire. Lorsque la taille du code compilé atteint une limite prédéfinie, la compilation native s'arrête et le code restant s'exécute de manière non native. Cela rend essentiel le choix soigneux des scripts pour la compilation native.
Pour surveiller la taille du code natif des fonctions et des scripts individuels :
- Assurez-vous que vous êtes en vue Serveur via le bouton client/serveur toggle.
- Invitez debug.dumpcodesize() depuis la Command Bar.
Dans la fenêtre Output, vous verrez le nombre total de scripts et de fonctions qui ont été compilés de manière native jusqu'au point d'invocation, la mémoire consommée par leur code natif, et la limite de taille de code natif. Après le résumé, vous verrez un tableau pour chaque script compilé de manière native dans l'ordre décroissant de la taille du code.

Pour chaque script, la sortie affiche le nombre de fonctions compilées et la consommation de mémoire du code natif. Chaque fonction est ensuite listée dans l'ordre décroissant de la taille du code natif, avec des fonctions anonymes affichées comme [anonymous] et des scripts entiers affichés comme [top level]. Dans la dernière colonne, le pourcentage est calculé par rapport à la limite de taille du code natif. Notez que la taille du code natif des fonctions est rapportée avec précision mais la consommation de mémoire pour les scripts est arrondie au plus proche seuil de page.
Limites et dépannage
Compiler le code en instructions pour un CPU particulier nécessite une mémoire de stockage supplémentaire. De plus, les optimisations pour des fonctions complexes peuvent prendre trop de temps à effectuer. Atteindre une limite interne rapportera une erreur dans la fenêtre Output de Studio, notamment :
Fonction 'f' à la ligne 20 a dépassé la limite d'instructions du bloc de code unique
Cette erreur signifie qu'un bloc de code unique à l'intérieur d'une fonction a utilisé plus de 64K instructions. Cela peut être évité en simplifiant la fonction ou en la divisant en fonctions individuelles plus petites.
Fonction 'f' à la ligne 20 a dépassé la limite de bloc de code de fonction
Cette erreur signifie qu'une seule fonction contient plus de 32K blocs internes de code. Les blocs internes de code ne correspondent pas exactement aux blocs de contrôle de flux dans votre script, mais cette erreur peut être évitée en simplifiant le flux de contrôle dans la fonction ou en la divisant en fonctions individuelles plus petites.
Fonction 'f' à la ligne 200 a dépassé la limite d'instructions totale du module
Cette erreur signifie que, au total, la fonction a atteint une limite d'un million d'instructions pour l'ensemble du script. Dans certains cas, la fonction signalée elle-même peut avoir beaucoup d'instructions, ou la limite peut avoir été atteinte par des fonctions plus tôt dans le script. Pour éviter ce problème, il est recommandé de soit déplacer des fonctions particulièrement grandes dans un script non natif séparé, soit d'utiliser @native sur les autres fonctions. Vous pouvez également essayer de marquer ce script séparé avec --!native, mais un million d'instructions consomme beaucoup de mémoire et vous pourriez dépasser la limite de mémoire.
Fonction 'f' à la ligne 20 a rencontré un échec de réduction interne (ou)
Erreur interne : La génération de code natif a échoué (réduction d'assemblage)
Parfois, une fonction contient des morceaux de code complexes que le compilateur de code natif ne peut actuellement pas gérer. Pour éviter cette erreur, inspectez les expressions complexes dans le code et divisez-les ou simplifiez-les, mais envisagez également d'ouvrir un rapport de bug avec un exemple de code qui a échoué pour cette raison.
Limite d'allocation de mémoire atteinte pour la génération de code natif
Cette erreur signifie que la limite globale de mémoire pour les données de code natif a été atteinte. Pour éviter cela, essayez de supprimer --!native des scripts les plus gourmands en mémoire, ce qui permet à plus de petits scripts de rester sous la limite. Alternativement, déplacez les grandes fonctions ou les fonctions appelées rarement dans un module non natif séparé.