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 lourds à 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 :¹
--!native
print("Bonjour depuis le code natif !")Cela active la génération de code natif pour toutes les fonctions du script, ainsi que pour le scope de niveau supérieur, si cela est jugé rentable. Aucun changement supplémentaire n'est requis ; le comportement des scripts exécutés nativement 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)
endMeilleures 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 peut ê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 quand il est préférable de 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 rapidement, mais la génération de code natif a certains inconvénients :
- Le temps de compilation du code est requis, ce qui peut augmenter le temps de démarrage des serveurs.
- Une 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 résolus par une utilisation judicieuse 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 provoquer une dé-optimisation ou un retour à l'exécution interprétée. Celles-ci incluent :
- 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 appeler foo(true) lorsque foo est déclaré comme function foo(arg: string). N'oubliez pas d'utiliser toujours des annotations de type correctes.
Lors de l'utilisation du 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 ne semble pas s'exécuter 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 accédée 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, entraînant une exécution de 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 étant 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
endOutils Studio
Les outils 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 des frames de la pile d'appels qui s'exécutent de manière native.
Notez également que lors du débogage du code sélectionné pour la compilation native, le placement 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 du placement de points d'arrêt, de l'utilisation de code déconseillé, ou d'annotations de type mismatched.
Tas Luau
Dans le profileur Luau heap, la mémoire occupée par les fonctions natives s'affiche comme des éléments [native] dans le graphique.

Analyse de 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 est exécuté de manière non native. Cela rend essentiel de choisir les scripts avec soin pour la compilation native.
Pour surveiller la taille du code natif des fonctions et scripts individuels :
- Assurez-vous que vous êtes en vue Serveur via le bouton client/serveur.
- Appelez debug.dumpcodesize() depuis la Barre de Commande.
Dans la fenêtre Sortie, vous verrez le nombre total de scripts et de fonctions qui ont été compilés de manière native jusqu'au moment de l'invocation, la mémoire consommée par leur code natif, et la limite de taille du code natif. Après le résumé, vous verrez un tableau pour chaque script compilé de manière native par ordre décroissant de taille de 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 par ordre décroissant de taille de 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 de code natif. Notez que la taille de code natif des fonctions est rapportée avec précision, mais la consommation de mémoire pour les scripts est arrondie à la taille de page la plus proche.
Limites et dépannage
Compiler du 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 signalera une erreur dans la fenêtre Sortie de Studio, y compris :
Fonction 'f' à la ligne 20 a dépassé la limite d'instructions de bloc de code unique
Cette erreur signifie qu'un seul bloc de code à 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 de code internes. Les blocs de code internes ne correspondent pas exactement aux blocs de contrôle de flux dans votre script, mais cette erreur peut être évitée en simplifiant le contrôle de flux dans la fonction ou en la divisant en fonctions individuelles plus petites.
Fonction 'f' à la ligne 200 a dépassé la limite totale d'instructions de module
Cette erreur signifie qu'en tout, la fonction a atteint une limite de 1 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 déplacer des fonctions particulièrement grandes dans un script non natif séparé ou d'utiliser @native sur les autres fonctions. Vous pouvez également essayer de marquer ce script séparé avec --!native, mais 1 million d'instructions prend 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 bogue 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 de mémoire globale pour les données de code natif a été atteinte. Pour éviter cela, essayez de retirer --!native des scripts les plus gourmands en mémoire, permettant à plus de petits scripts de s'inscrire sous la limite. Alternativement, déplacez les grandes fonctions ou celles appelées peu fréquemment dans un module non natif séparé.