Dzięki wsparciu Luau dla generacji kodu natywnego, skrypty¹ w twojej grze mogą być kompilowane bezpośrednio do instrukcji kodu maszynowego, które wykonują procesory, zamiast regularnego bajtowego kodu, na którym działa maszyna wirtualna Luau. Ta funkcja może poprawić szybkość wykonania dla niektórych wspieranych skryptów, szczególnie tych z dużą ilością obliczeń numerycznych i niewielką liczbą wywołań ciężkich bibliotek Luau lub interfejsów API Roblox.
1 Generacja kodu natywnego jest wspierana tylko dla skryptów po stronie serwera oraz skryptów po stronie klienta na urządzeniach z systemem Android. W przyszłości mogą być wspierane dodatkowe urządzenia.
Włączanie generacji kodu natywnego
Aby włączyć generację kodu natywnego dla Script, dodaj komentarz --!native na górze:²
--!native
print("Witaj z kodu natywnego!")To włącza generację kodu natywnego dla wszystkich funkcji w skrypcie oraz dla zasięgu najwyższego poziomu, jeśli uznane to zostanie za opłacalne. Nie są wymagane dodatkowe zmiany; zachowanie skryptów wykonujących natywnie jest dokładnie takie samo jak wcześniej, a tylko wydajność jest inna. Wszystkie funkcje języka Luau i wszystkie interfejsy API Roblox pozostają wspierane.
Alternatywnie, możesz włączyć generację kodu natywnego dla pojedynczej funkcji, dodając atrybut @native:
@native
local function f(x)
return (x + 1)
endNajlepsze praktyki
Poniższe wskazówki pomogą ci w pełni wykorzystać generację kodu natywnego:
Najlepiej jest włączyć tę funkcję w skryptach, które wykonują dużo obliczeń bezpośrednio w Luau. Jeśli masz wiele operacji matematycznych na tabelach, a szczególnie na typach buffer, skrypt może być dobrym kandydatem.
Zaleca się, abyś zmierzył czas, jaki skrypt lub funkcja zajmuje z i bez kompilacji natywnej, aby ocenić, kiedy najlepiej ją wykorzystać. Narzędzie Profiler skryptów może mierzyć wydajność funkcji, aby podejmować świadome decyzje.
Może być kuszące umieścić komentarz --!native w każdym skrypcie, na wypadek gdyby niektóre z nich działały szybciej, ale generacja kodu natywnego ma pewne wady:
- Wymagany jest czas kompilacji kodu, co może zwiększyć czas uruchamiania serwerów.
- Dodatkowa pamięć jest zajmowana na przechowywanie natywnie skompilowanego kodu.
- Istnieje limit na całkowitą dozwoloną ilość natywnie skompilowanego kodu w grze.
Te problemy można rozwiązać przez rozsądne użycie atrybutu @native.
Kod do unikania
Chociaż wszystkie funkcje będą działać tak samo z włączoną lub wyłączoną generacją kodu natywnego, niektóre z nich nie będą działać natywnie i mogą powodować de‑optymalizację lub powrót do interpretowanego wykonania. Należą do nich:
- Użycie różnych wbudowanych funkcji Luau, takich jak math.asin() z argumentami nienumerycznymi.
- Przekazywanie niewłaściwie typowanych parametrów do typowanych funkcji, na przykład wywołanie foo(true), gdy foo jest zadeklarowane jako function foo(arg: string). Pamiętaj, aby zawsze używać poprawnych adnotacji typów.
Podczas korzystania z Profilera skryptów możesz porównać czas zajmowany przez regularną wersję funkcji z tą skompilowaną natywnie. Jeśli funkcja wewnątrz skryptu --!native lub oznaczona @native nie wydaje się działać natywnie, jeden lub więcej czynników z powyższej listy może wywoływać de‑optymalizację.
Używaj adnotacji typów
Generacja kodu natywnego stara się wywnioskować najbardziej prawdopodobny typ dla danego zmiennej, aby zoptymalizować ścieżki kodu. Na przykład zakłada się, że a + b jest wykonywane na liczbach, lub że tabela jest dostępna w t.X. Biorąc pod uwagę przeciążanie operatorów, jednak a i b mogą być tabelami lub typami Vector3, lub t może być typem danych Roblox.
Chociaż generacja kodu natywnego będzie wspierać dowolny typ, błędne przewidywania mogą wywołać niepotrzebne kontrole, co skutkuje wolniejszym wykonaniem kodu.
Aby rozwiązać niektóre powszechne problemy, adnotacje typów Luau na argumentach funkcji są sprawdzane, ale szczególnie zaleca się adnotowanie argumentów Vector3:
--!native
-- "v" jest zakładane jako tabela; funkcja działa wolniej z powodu kontroli tabeli
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- "v" jest zadeklarowane jako Vector3; generowany jest kod specjalizowany dla wektorów
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
endNarzędzia Studio
Poniższe narzędzia Studio są wspierane dla skryptów --!native i funkcji @native.
Debugowanie
Ogólne debugowanie skryptów jest wspierane, ale widoki dla lokalnych/upvalue mogą być niekompletne i brakować zmiennych z ramek stosu wywołań, które są wykonywane natywnie.
Należy również zauważyć, że podczas debugowania kodu wybranego do kompilacji natywnej, umieszczanie punktów przerwania wyłączy natywne wykonanie dla tych funkcji.
Profiler skryptów
W Profilerze skryptów funkcje wykonujące natywnie wyświetlają <native> obok nich:

Jeśli funkcja oznaczona @native lub znajdująca się w skrypcie --!native nie pokazuje adnotacji <native>, ta funkcja może nie być wykonywana natywnie z powodu umiejscowienia punktów przerwania, użycia niedozwolonego kodu lub niedopasowanych adnotacji typów.
Stos Luau
W profilerze Stos Luau pamięć zajmowana przez natywne funkcje wyświetla się jako elementy [native] w wykresie.

Analiza rozmiaru
Każdy natywnie skompilowany skrypt zużywa pamięć. Gdy rozmiar skompilowanego kodu osiągnie zdefiniowany limit, kompilacja natywna zatrzymuje się, a pozostały kod jest wykonywany nienatywnie. Dlatego ważne jest, aby starannie wybierać skrypty do kompilacji natywnej.
Aby monitorować rozmiar kodu natywnego poszczególnych funkcji i skryptów:
- Upewnij się, że jesteś w widoku Serwera za pomocą przycisku przełączania klient/serwer.
- Wywołaj debug.dumpcodesize() z Paska poleceń.
W oknie Wyjście zobaczysz całkowitą liczbę skryptów i funkcji, które zostały natywnie skompilowane do momentu wywołania, pamięć zajmowaną przez ich natywny kod oraz limit rozmiaru kodu natywnego. Po podsumowaniu zobaczysz tabelę dla każdego natywnie skompilowanego skryptu w porządku malejącym według rozmiaru kodu.

Dla każdego skryptu, wyjście wyświetla liczbę skompilowanych funkcji oraz zużycie pamięci kodu natywnego. Każda funkcja jest następnie wymieniana w porządku malejącym według rozmiaru kodu natywnego, a funkcje anonimowe są pokazane jako [anonymous], a całe skrypty jako [top level]. W ostatniej kolumnie procent obliczany jest w odniesieniu do limitu rozmiaru kodu natywnego. Należy pamiętać, że rozmiar kodu natywnego funkcji jest raportowany dokładnie, ale zużycie pamięci dla skryptów jest zaokrąglane do najbliższego rozmiaru strony.
Limity i rozwiązywanie problemów
Kompilacja kodu do instrukcji dla konkretnego CPU wymaga dodatkowej pamięci do przechowywania. Dodatkowo, optymalizacje dla złożonych funkcji mogą zająć zbyt dużo czasu. Przekroczenie wewnętrznego limitu zgłosi błąd w oknie Wyjście Studio, w tym:
Funkcja 'f' w linii 20 przekroczyła limit instrukcji pojedynczego bloku kodu
Ten błąd oznacza, że pojedynczy blok kodu wewnątrz funkcji użył więcej niż 64K instrukcji. Można tego uniknąć, upraszczając funkcję lub dzieląc ją na mniejsze funkcje.
Funkcja 'f' w linii 20 przekroczyła limit bloku kodu funkcji
Ten błąd oznacza, że pojedyncza funkcja zawiera więcej niż 32K wewnętrznych bloków kodu. Wewnętrzne bloki kodu nie dokładnie odpowiadają blokom przepływu sterowania w twoim skrypcie, ale ten błąd można uniknąć, upraszczając przepływ sterowania w funkcji lub dzieląc ją na mniejsze funkcje.
Funkcja 'f' w linii 200 przekroczyła całkowity limit instrukcji modułu
Ten błąd oznacza, że funkcja osiągnęła limit 1 miliona instrukcji dla całego skryptu. W niektórych przypadkach zgłoszona funkcja sama może mieć dużo instrukcji, lub limit mógł zostać osiągnięty przez funkcje wcześniejsze w skrypcie. Aby uniknąć tego problemu, zaleca się przeniesienie szczególnie dużych funkcji do osobnego nienatywnego skryptu lub użycie @native w innych funkcjach. Możesz także spróbować oznaczyć ten osobny skrypt jako --!native, ale 1 milion instrukcji zajmuje dużo pamięci i możesz przekroczyć limit pamięci.
Funkcja 'f' w linii 20 napotkała wewnętrzny błąd obniżania (lub)
Błąd wewnętrzny: Generacja kodu natywnego nie powiodła się (obniżanie asemblera)
Czasami funkcja zawiera złożone fragmenty kodu, których kompilator kodu natywnego obecnie nie może obsłużyć. Aby uniknąć tego błędu, sprawdź złożone wyrażenia w kodzie i podziel je lub uprość, ale także rozważ otwarcie zgłoszenia błędu z przykładem kodu, który nie powiódł się z tego powodu.
Osiągnięto limit alokacji pamięci dla generacji kodu natywnego
Ten błąd oznacza, że osiągnięto ogólny limit pamięci dla danych kodu natywnego. Aby tego uniknąć, spróbuj usunąć --!native z bardziej pamięciożernych skryptów, co pozwoli na zmieszczenie większej liczby mniejszych skryptów w limicie. Alternatywnie, przenieś duże lub rzadko wywoływane funkcje do osobnego nienatywnego modułu.