Generación de código nativo

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

Con el soporte de Luau para la generación de código nativo, los scripts del lado del servidor en tu experiencia se pueden compilar directamente en las instrucciones de código de máquina que ejecutan las CPUs, en lugar de código de bytes regular que la VM de Luau opera.Esta característica se puede utilizar para mejorar la velocidad de ejecución de algunos scripts en el servidor, en particular aquellos que tienen mucha computación numérica sin usar demasiadas llamadas de biblioteca Luau o de API de Roblox.

Habilitar la generación de código nativo

Para habilitar la generación de código nativo para un Script , agregue el comentario --!native en la parte superior:¹


--!native
print("Hello from native code!")

Esto habilita la generación de código nativo para todas las funciones en el script y el alcance de nivel superior, si se considera rentable.No se requieren cambios adicionales; el comportamiento de los scripts que se ejecutan nativamente es exactamente igual que antes y solo el rendimiento es diferente.Todas las características del idioma Luau y todas las API de Roblox siguen siendo admitidas.

Alternativamente, puedes habilitar la generación de código nativo para una función individual agregando el atributo @native:


@native
local function f(x)
return (x + 1)
end
1 En el futuro, algunos scripts pueden comenzar automáticamente a ejecutarse nativamente si se determina que es rentable, pero se requieren comentarios manualmente colocados --!native actualmente.

Mejores prácticas

Los siguientes consejos te ayudarán a aprovechar al máximo la generación de código nativo:

  • Es mejor habilitar esta función dentro de los scripts que realizan mucha computación directamente dentro de Luau.Si tienes muchas operaciones matemáticas en tablas y especialmente buffer tipos, el script puede ser un buen candidato.

  • Solo las funciones del script se compilan nativamente.El código en el alcance superior exterior suele ejecutarse solo una vez y no se beneficia tanto como las funciones que se llaman muchas veces, especialmente las que se llaman en cada marco.

  • Se recomienda que midas el tiempo que tarda un script o una función con y sin compilación nativa para juzgar cuándo es mejor usarla.La herramienta Perfilador de scripts puede medir el rendimiento de las funciones para tomar decisiones informadas.

  • Puede ser tentador colocar el comentario --!native en cada guión sólo en caso de que algunos de ellos se ejecuten más rápido, pero la generación de código nativo tiene algunas desventajas:

    • Se requiere el tiempo de compilación de código que puede aumentar el tiempo de inicio de los servidores.
    • La memoria adicional está ocupada para almacenar código compilado nativamente.
    • Hay un límite en la cantidad total permitida de código compilado nativamente en una experiencia.

Estos problemas se pueden abordar con un uso judicial del atributo @native.

Código para evitar

Aunque todas las funciones se comportarán de la misma manera con o sin generación de código nativo habilitada, algunas de ellas no se ejecutarán nativamente y podrían causar una de optimización o un fallo a la ejecución interpretada.Estos incluyen:

  • Uso de llamadas obsoletas getfenv() / setfenv() .
  • Uso de varias funciones integradas de Luau como math.asin() con argumentos no numéricos.
  • Pasar parámetros mal tipados a funciones tipificadas, por ejemplo, llamar foo(true) cuando foo se declare como function foo(arg: string).Recuerde siempre usar las anotaciones de tipo correcto .

Al usar el Perfilador de scripts, puedes comparar el tiempo tomado por una versión regular de la función versus la compilada nativamente.Si una función dentro de un --!native script o marcada con @native no parece estar ejecutándose nativamente, uno o más factores de la lista anterior pueden estar desencadenando la desoptimización.

Usar anotaciones de tipo

Los intentos de generación de código nativo intentan inferir el tipo más probable para una variable dada con el fin de optimizar los caminos de código.Por ejemplo, se asume que a + b se realiza en números, o que una tabla se accede en t.X .Dada la sobrecarga del operador, sin embargo, a y b pueden ser tablas o Vector3 tipos, o t puede ser un tipo de datos de Roblox.

Mientras que la generación de código nativo admitirá cualquier introducir, las predicciones incorrectas pueden desencadenar inspecciones innecesarias, lo que resulta en una ejecución de código más lenta.

Para resolver algunos problemas comunes, Luau tipo anotaciones en los argumentos de función se verifican, pero se recomienda especialmente anotar Vector3 argumentos:


--!native
-- se asume que "v" es una tabla; la función se ejecuta más lentamente debido a las comprobaciones de tabla
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- Se declara que "v" es un Vector3; se genera código especializado para vectores
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
end

Herramientas de estudio

Se soporta la siguiente herramienta de Studio para --!native@native .

Depuración

Se admite el depurado general de scripts, pero las vistas para los locales/valores ascendentes pueden estar incompletas y faltar variables de pila de llamadas que se ejecutan de forma nativa.

Tenga en cuenta también que al depurar el código seleccionado para la compilación nativa, colocar puntos de interrupción desactivará la ejecución nativa para esas funciones.

Perfilador de scripts

En el Perfilador de scripts, las funciones que se ejecutan nativamente muestran <native> junto a ellas:

Example of native functions flagged in the Script Profiler

Si una función marcada @native no muestra la anotación dentro de un script, esa función puede no estar siendo ejecutada nativamente debido a la colocación de punto de interrupción , el uso de código descorazonado o las anotaciones de tipo no coincidentes .

Pila de Luau

En el perfilador de pila Luau, la memoria tomada por las funciones nativas se muestra como [native] elementos en el gráfico.

Example of native memory usage flagged in the Luau Heap profiler

Análisis de tamaño

Cada script compilado nativamente consume memoria.Cuando el tamaño del código compilado alcanza un límite predefinido, la compilación nativa se detiene y el código restante se ejecuta sin natividad.Esto hace que sea esencial elegir scripts cuidadosamente para la compilación nativa.

Para monitorear el tamaño del código nativo de funciones e scripts individuales:

  1. Asegúrate de estar en vista del servidor a través del botón cliente/servidor toggle.
  2. Invoca debug.dumpcodesize() desde la barra de comandos.

En la ventana Salida, verás el número total de scripts y funciones que se han compilado nativamente hasta el punto de invocación, la memoria consumida por su código nativo y el límite de tamaño del código nativo.Después del resumen, verás una tabla para cada script nativamente compilado en orden descendente de tamaño de código.

Example of native code size displayed in the Output window.

Para cada script, la salida muestra el número de funciones compiladas y el consumo de memoria de código nativo.Cada función se enumerará en orden descendente del tamaño del código nativo, con funciones anónimas mostradas como [anonymous] y scripts completos mostrados como [top level].En la columna final, el porcentaje se calcula con respecto al límite de tamaño del código nativo.Tenga en cuenta que el tamaño del código nativo de las funciones se informa con precisión, pero el consumo de memoria para los scripts se redondea a la siguiente página más cercana.

Límites y solución de problemas

Compilar código en instrucciones para una determinada CPU requiere memoria de almacenamiento adicional.Además, las optimizaciones para funciones complejas pueden tardar demasiado en ejecutarse.Golpear un límite interno informará un error en la ventana Salida de Studio, incluyendo:

La función 'f' en la línea 20 superó el límite de instrucción de bloque de código único

Este error significa que un solo bloque de código dentro de una función usó más de 64K instrucciones.Esto se puede evitar simplificando la función o dividiéndola en funciones más pequeñas individuales.

La función 'f' en la línea 20 superó el límite de código de función

Este error significa que una sola función contiene más de 32K bloques internos de código.Los bloques de código internos no se mapean exactamente a los bloques de flujo de control en tu script, pero este error se puede evitar simplificando el flujo de control en la función o dividiéndolo en funciones más pequeñas individuales.

La función 'f' en la línea 200 superó el límite de instrucciones de módulo total

Este error significa que, en total, la función ha alcanzado un límite de 1 millón de instrucciones para todo el script.En algunos casos, la propia función informada puede tener muchas instrucciones, o el límite puede haber sido alcanzado por funciones anteriores en el script.Para evitar este problema, se recomienda mover funciones particularmente grandes a un script separado no nativo o usar @native en las otras funciones.También puedes intentar marcar ese script separado con --!native , pero 1 millón de instrucciones ocupa mucha memoria y puedes exceder el límite de memoria

*La función 'f' en la línea 20 encontró un fallo de reducción interna *(o) Error interno: generación de código nativo falló (reducción de ensamblaje)

A veces, una función contiene bits complejos de código que el compilador de código nativo no puede controladoractualmente.Para evitar este error, inspeccione las expresiones complejas en el código y diviértelas o simplifíquelas, pero también considere abrir un informe de errores con un ejemplo del código que falló por este motivo.

Límite de asignación de memoria alcanzado para la generación de código nativo

Este error significa que se ha alcanzado el límite de memoria general para los datos del código nativo.Para evitar esto, intenta eliminar --!native de los scripts más intensivos en memoria, permitiendo que más pequeños scripts encajen dentro del límite.Alternativamente, mueve funciones grandes o poco llamadas a un módulo no nativo separado.