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 juego pueden ser compilados directamente en las instrucciones de código de máquina que ejecutan las CPU, en lugar de un bytecode regular que opera la VM de Luau. Esta característica puede utilizarse para mejorar la velocidad de ejecución de algunos scripts en el servidor, en particular aquellos que realizan muchos cálculos numéricos sin usar demasiadas llamadas pesadas a la biblioteca de Luau o la API de Roblox.

Habilitar la generación de código nativo

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


--!native
print("¡Hola desde el código nativo!")

Esto habilita la generación de código nativo para todas las funciones en el script, y el ámbito de nivel superior, si se considera rentable. No se requieren cambios adicionales; el comportamiento de los scripts que se ejecutan nativamente es exactamente el mismo que antes y solo la performance es diferente. Todas las características del lenguaje Luau y todas las APIs de Roblox siguen estando soportadas.

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 podrían comenzar a ejecutarse automáticamente de manera nativa si se determina que es rentable, pero actualmente se requieren comentarios --!native colocados manualmente.

Mejores prácticas

Los siguientes consejos te ayudarán a beneficiarte más de la generación de código nativo:

  • Es mejor habilitar esta característica dentro de scripts que realizan muchos cálculos directamente dentro de Luau. Si tienes muchas operaciones matemáticas en tablas y especialmente tipos buffer, el script puede ser un candidato adecuado.

  • Solo las funciones del script se compilan de manera nativa. El código en el ámbito exterior superior a menudo se ejecuta solo una vez y no se beneficia tanto como las funciones que se llaman muchas veces, especialmente aquellas que se llaman cada cuadro.

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

  • Puede ser tentador colocar el comentario --!native en cada script por si acaso algunos de ellos se ejecutan más rápido, pero la generación de código nativo tiene algunas desventajas:

    • Se requiere tiempo de compilación de código, lo que puede aumentar el tiempo de inicio de los servidores.
    • Se ocupa memoria adicional para almacenar el código compilado de manera nativa.
    • Hay un límite en la cantidad total permitida de código compilado de manera nativa en un juego.

Estos problemas se pueden abordar mediante un uso juicioso del atributo @native.

Código a evitar

Si bien todas las características se comportarán de la misma manera con o sin la generación de código nativo habilitada, algunas de ellas no se ejecutarán de manera nativa y pueden causar desoptimización o un retroceso 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 de tipo incorrecto a funciones tipadas, por ejemplo, llamar a foo(true) cuando foo se declara como function foo(arg: string). Recuerda siempre usar las anotaciones de tipo correctas.

Al usar el Script Profiler, puedes comparar el tiempo que toma una versión regular de la función frente a la que se compila de manera nativa. Si una función dentro de un script --!native o marcada con @native no parece estar ejecutándose de manera nativa, uno o más factores de la lista anterior pueden estar provocando desoptimización.

Usa anotaciones de tipo

La generación de código nativo intenta inferir el tipo más probable para una variable dada con el fin de optimizar los caminos de código. Por ejemplo, se supone que a + b se realiza en números, o que se accede a una tabla en t.X. Sin embargo, dado el sobrecargado de operadores, a y b pueden ser tablas o tipos Vector3, o t puede ser un tipo de dato de Roblox.

Si bien la generación de código nativo admitirá cualquier tipo, las predicciones incorrectas pueden desencadenar verificaciones innecesarias, lo que resulta en ejecuciones de código más lentas.

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


--!native
-- "v" se supone que es una tabla; la función se ejecuta más lento debido a las verificaciones de tabla
local function sumaComponentesLenta(v)
return v.X + v.Y + v.Z
end
-- "v" se declara como un Vector3; se genera código especializado para vectores
local function sumaComponentesRápida(v: Vector3)
return v.X + v.Y + v.Z
end

Herramientas de Studio

Las siguientes herramientas de Studio son compatibles con los scripts --!native y las funciones @native.

Depuración

La depuración general de scripts es compatible, pero las vistas para variables locales/upvalues pueden estar incompletas y faltar variables de los marcos de pila de llamadas que se están ejecutando de manera nativa.

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

Script Profiler

En el Script Profiler, las funciones que se ejecutan de manera nativa muestran <native> junto a ellas:

Ejemplo de funciones nativas señaladas en el Script Profiler

Si una función marcada con @native o dentro de un script --!native no muestra la anotación <native>, es posible que esa función no esté ejecutándose de manera nativa debido a la colocación de un punto de interrupción, al uso de código desaconsejado o a anotaciones de tipo no coincidentes type annotations.

Heap de Luau

En el perfilador del Heap de Luau, la memoria ocupada por funciones nativas se muestra como elementos [native] en el gráfico.

Ejemplo de uso de memoria nativa señalado en el perfilador del Heap de Luau

Análisis de tamaño

Cada script compilado de manera nativa 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 de forma no nativa. Esto hace que sea esencial elegir los scripts con cuidado para la compilación nativa.

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

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

En la ventana de Output, verás el número total de scripts y funciones que han sido compilados de manera nativa hasta el momento de la invocación, la memoria consumida por su código nativo y el límite de tamaño de código nativo. Tras el resumen, verás una tabla para cada script compilado de manera nativa en orden descendente de tamaño de código.

Ejemplo del tamaño de código nativo mostrado en la ventana de Output.

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

Límite y solución de problemas

Compilar código en instrucciones para una CPU particular requiere memoria adicional de almacenamiento. Además, las optimizaciones para funciones complejas pueden llevar demasiado tiempo para realizarse. Al alcanzar un límite interno, se informará un error en la ventana de Output de Studio, incluido:

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

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

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

Este error significa que una sola función contiene más de 32K bloques internos de código. Los bloques internos de código 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éndola en funciones individuales más pequeñas.

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

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 función reportada en sí puede tener muchas instrucciones, o el límite puede haber sido alcanzado por funciones antes en el script. Para evitar este problema, se recomienda mover funciones particularmente grandes a un script no nativo separado 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 es posible que superes el límite de memoria.

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

A veces, una función contiene partes de código complejas que el compilador de código nativo no puede manejar actualmente. Para evitar este error, inspecciona expresiones complejas en el código y divídelas o simplifícalas, pero también considera abrir un informe de error con un ejemplo del código que falló por esta razón.

Se alcanzó el límite de asignación de memoria para la generación de código nativo

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

©2026 Roblox Corporation. Roblox, el logotipo de Roblox y "Powering Imagination" son algunas de nuestras marcas registradas y no registradas en los Estados Unidos y otros países.