Génération de code natif

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

Avec le soutien Luau pour la génération de code natif, les scripts côté serveur dans votre expérience peuvent être compilés directement dans les instructions de code de machine que les processeurs exécuter, plutôt que le code binaire standard que le serveur exécute. Cette fonctionnalité peut être utilisée pour améliorer la vitesse d'exécution pour certains scripts sur le serveur, en particulier ceux qui ont beaucoup de calculs numériques sans utiliser trop de mémoire de bibliothèque Luau ou d'appels d'API Roblox.

Activer le natif

Pour activer la génération de code native pour un Script, ajoutez le commentaire --!native au début :¹


--!néo
print("Hello from native code!")

Cela permet la génération de code natif pour toutes les fonctions dans le script, et la portée supérieure, si elle est jugée rentable. Aucun changement supplémentaire n'est requis ; le comportement de la nativité des scripts est exactement le même qu'avant et seul le rendu est différent. Toutes les fonctionnalités de la langue Luau et toutes les API Roblox sont toujours 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
1 Dans le futur, certains scripts pourraient automatiquement commencer à s'exécuter nativement si elle est déterminée à être rentable, mais placée manuellement les commentaires --!native sont actuellement requis.

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 des scripts qui effectuent beaucoup de calculs directement à l'intérieur de Luau. Si vous avez beaucoup d'opérations mathématiques sur les tables et surtout les types buffer, le script peut être un bon candidat.

  • Seules les fonctions du script sont compilées nativement. Le code dans le scope extérieur supérieur est souvent exécuté une fois et ne bénéficie pas autant que les fonctions qui sont appelées plusieurs fois, surtout celles qui sont appelées chaque cadre.

  • Il est recommandé de mesurer le temps qu'il met un script ou une fonction pour exécuter avec ou sans compilation native pour juger quand il est préférable de l'utiliser. L'outil Script Profiler peut mesurer les performances des fonctions pour prendre des décisions éclairées.

  • Il peut être tentant de placer le commentaire --!native dans chaque script juste en cas de besoin pour que certains d'entre eux s'exécutent plus rapidement, mais la génération de code natif a quelques inconvénients :

    • Temps de compilation du code requis qui peut augmenter le temps de démarrage des serveurs.
    • La mémoire supplémentaire est occupée pour stocker le code compilé nativement.
    • Il y a une limite sur la quantité totale de code compilé nativement dans une expérience.

Ces problèmes peuvent être abordés en utilisant judicieusement l'attribut @native.

Code à éviter

Bien que toutes les fonctionnalités se comportent la même avec ou sans génération de code natif activé, certaines d'entre elles ne s'exécuteront pas nativement et peuvent causer une déoptimisation ou une erreur d'exécution interprétée. Cela inclut :

  • Utilisation de getfenv() / setfenv() appels.
  • Utilisation de diverses fonctions intégrées Luau comme math.asin() avec des arguments non numériques.
  • Passer les paramètres mal écrits à des fonctions, par exemple en appelant foo(true) lorsque foo est déclaré comme function foo(arg: string). N'oubliez pas d'utiliser toujours les bonnes 2>anneaux de type2>.

Lors de l'utilisation du profilateur de script, vous pouvez comparer le temps pris par une version régulière de la fonction contre la version compilée natifment. Si une fonction à l'intérieur d'un --!native script ou marquée par un 2> native2> script ou marqué avec un 5> optimisation déconnectée5> facteur de la liste ci-dessus, l'

Utiliser les types d'annonces

La génération de code native essaye d'inférer le type le plus probable pour une variable donnée afin d'optimiser les chemins de code. Par exemple, il est supposé que a + b > est exécuté sur les numéros, ou que une table

Bien que la génération de code native prendra en charge n'importe quel taper, les mauvaises prédictions peuvent déclencher des vérifications inutiles, ce qui entraînera une exécution de code plus lente.

Pour résoudre certains problèmes communs, Luau type des annotaciones sur les arguments de fonction sont vérifiées, mais il est spécialement recommandé d'annuler Vector3 des arguments :


--!néo
-- « v » est supposé être une table ; la fonction fonctionne plus lentement en raison de vérifications de table
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- « v » est déclaré être un Vector3 ; le code spécifique aux vécteurs est généré
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
end

Outil de studio

Les outils suivants du studio sont pris en charge pour --!native scripts et @native de 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 manquantes de variables à partir de cadres d'appel qui s'exécutent natifement.

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.

Profil de script

Dans le profil de script, les fonctions s'exécutant nativement affichent <native> à côté d'elles :

Example of native functions flagged in the Script Profiler

Si une fonction marquée @native ou à l'intérieur d'un --!native script n'affiche pas l'animation de <native>, ce que fonction ne peut pas exécuter en raison de la rupture de 2> breakpoint2> ou du placement, de l'utilisation de 5> code découragé5>

Tas de Luau

Dans le profiler Luau Heap, la mémoire prise par les fonctions natives s'affiche comme [native] éléments dans le graph.

Example of native memory usage flagged in the Luau Heap profiler

Analyse de la taille

Chaque script natifement compilé 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é en mode non natif. Cela rend nécessaire de choisir soigneusement les scripts pour la compilation native.

Pour surveiller la taille du code natif des fonctions et des scripts individuels :

  1. Assurez-vous que vous êtes dans une vue du serveur par le biais du bouton client/serveur toggle .
  2. Invokez debug.dumpcodesize() depuis le Bar de commande .

Dans la fenêtre sortie, vous verrez le nombre total de scripts et de fonctions qui ont été compilés nativement jusqu'au point d'invocation, la mémoire consommée par leur code natif et la limite de taille du code natif. Après le sommaire, vous verrez un tableau pour chaque script compilé nativement dans l'ordre décroissant de la taille du code.

Example of native code size displayed in the Output window.

Pour chaque script, la sortie affiche le nombre de fonctions compilées et la mémoire de code natif. Chaque fonction est ensuite listée dans un 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 colonne finale, le pourcentage est calculé en fonction de la taille du code natif des fonctions

Limites et débogage

Le fait de compiler du code en instructions pour un certain CPU nécessite une mémoire supplémentaire. De plus, les optimisations pour des fonctions complexes peuvent prendre trop de temps à s'exécuter. En frappant une limite interne, vous signalerez une erreur dans la fenêtre Sortie de Studio, y compris :

La fonction « f » à la ligne 20 a dépassé la limite d'instruction de bloc de code unique

Cette erreur signifie que le code d'un seul bloc dans une fonction a utilisé plus de 64K d'instructions. Cela peut être évité en simplifiant la fonction ou en la divisant en petites fonctions individuelles.

La fonction « f » à la ligne 20 a dépassé la limite de code de fonctionnalité.

Cette erreur signifie que une seule fonction contient plus de 32K blocs internes de code. Les blocs internes de code ne se traduisent pas exactement en blocs de contrôle dans votre script, mais cette erreur peut être évitée en simplifiant le flux de contrôle dans la fonction ou en le divisant en plusieurs petits blocs.

La fonction « f » à la ligne 200 a dépassé la limite totale d'instruction du module

Cette erreur signifie que, au total, 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 a peut-être été atteinte par des fonctions plus tôt dans le script. Pour éviter ce pro

*La fonction « f » à la ligne 20 a rencontré une erreur de réduction interne. *(ou) Erreur interne : la génération de code natif a échoué (baisse de l'assemblage).

Parfois, une fonction contient des bits de code complexes que le compilateur de code natif ne peut pas contrôleuractuellement. Pour éviter cette erreur, inspectez les expressions complexes dans le code et divisez-les ou simplifiez-les, mais également considérez l'ouverture d'un rapport d'erreur avec un exemple du 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 supprimer --!native > des scripts les plus mémoireux, ce qui permet à plus de petits scripts de s'inscrire dans la limite. Alternativement, déplacez de grandes ou infrequentes fonctions à un module non natif séparé.