Dzięki wsparciu dla generacji kodu natywnego w Luau, skrypty po stronie serwera twojej gry mogą być kompilowane bezpośrednio do instrukcji kodu maszynowego, które wykonują procesory, zamiast zwykłego kodu bajtowego, na którym działa maszyna wirtualna Luau. Ta funkcja może być używana w celu poprawy szybkości wykonania niektórych skryptów na serwerze, w szczególności tych, które mają dużo obliczeń numerycznych, nie wykorzystując zbyt wielu ciężkich wywołań biblioteki Luau lub API Roblox.
Włączanie generacji kodu natywnego
Aby włączyć generację kodu natywnego dla Script, dodaj komentarz --!native na górze:¹
--!nativeprint("Witaj z kodu natywnego!")
To włącza generację kodu natywnego dla wszystkich funkcji w skrypcie oraz dla najwyższego poziomu, jeśli uznaje się to za opłacalne. Nie są potrzebne dodatkowe zmiany; zachowanie skryptów wykonujących się natywnie jest dokładnie takie samo jak wcześniej, a różni się jedynie wydajnością. Wszystkie funkcje języka Luau oraz wszystkie API Roblox pozostają wspierane.
Alternatywnie, możesz włączyć generację kodu natywnego dla pojedynczej funkcji przez dodanie atrybutu @native:
@native
local function f(x)
return (x + 1)
end
Najlepsze praktyki
Następujące wskazówki pomogą ci najlepiej skorzystać z generacji kodu natywnego:
Najlepiej włączać tę funkcję w skryptach, które wykonują dużo obliczeń bezpośrednio w Luau. Jeśli masz dużo 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 jest z niej korzystać. Narzędzie Profilera skryptów może zmierzyć wydajność funkcji, aby podejmować świadome decyzje.
Może być kuszące umieszczanie komentarza --!native w każdym skrypcie, na wypadek, gdyby niektóre z nich działały szybciej, ale generacja kodu natywnego ma pewne wady:
- Wymagana jest czas kompilacji kodu, co może zwiększać czas uruchamiania serwerów.
- Zajmowana jest dodatkowa pamięć do przechowywania natywnie skompilowanego kodu.
- Istnieje limit całkowitej dozwolonej ilości natywnie skompilowanego kodu w grze.
Te problemy można rozwiązać przez rozważne użycie atrybutu @native.
Kodu do unikania
Chociaż wszystkie funkcje zachowają się tak samo z włączoną lub wyłączoną generacją kodu natywnego, niektóre z nich nie będą działać natywnie i mogą powodować deoptymalizację lub przejście na wykonanie interpretowane. 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łując foo(true), gdy foo jest zadeklarowana jako function foo(arg: string). Pamiętaj, aby zawsze używać poprawnych adnotacji typów.
Kiedy korzystasz z Profilera skryptów, możesz porównać czas wykonania zwykłej wersji funkcji z wersją skompilowaną natywnie. Jeśli funkcja wewnątrz skryptu --!native lub oznaczona jako @native nie wydaje się działać natywnie, jeden lub więcej czynników z powyższej listy może wywoływać deoptymalizację.
Używaj adnotacji typów
Generacja kodu natywnego stara się wnioskować 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. Jednak z uwagi na przeciążanie operatorów, a i b mogą być tabelami lub typami Vector3, lub t może być typem Roblox.
Chociaż generacja kodu natywnego będzie wspierać dowolny typ, nietrafione przewidywania mogą wywoływać niepotrzebne sprawdzenia, co prowadzi do wolniejszego wykonania kodu.
Aby rozwiązać niektóre powszechne problemy, sprawdzane są adnotacje typów Luau w argumentach funkcji, ale szczególnie zaleca się adnotowanie argumentów typu Vector3:
--!native
-- "v" jest domyślnie zakładane jako tabela; funkcja działa wolniej z powodu sprawdzeń tabel
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
end
Narzędzia Studio
Następujące narzędzia Studio są wspierane dla skryptów --!native i funkcji @native.
Debugowanie
Ogólne debugowanie skryptów jest wspierane, ale widoki dla lokalnych/upvalues mogą być niekompletne i brakować zmiennych z ramek stosów wywołań, które są wykonywane natywnie.
Zauważ także, ż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 się natywnie wyświetlają <native> obok nich:

Jeśli funkcja oznaczona jako @native lub wewnątrz skryptu --!native nie pokazuje adnotacji <native>, ta funkcja może nie być wykonywana natywnie z powodu umiejscowienia punktu przerwania, użycia zniechęcającego kodu lub niezgodnych adnotacji typów.
Stos pamięci Luau
W profilerze stosu pamięci Luau, pamięć zajmowana przez funkcje natywne wyświetla się jako elementy [native] na wykresie.

Analiza rozmiaru
Każdy natywnie skompilowany skrypt zużywa pamięć. Gdy rozmiar skompilowanego kodu osiągnie wcześniej określony limit, kompilacja natywna zatrzymuje się, a pozostały kod jest uruchamiany nienatywnie. Dlatego kluczowe jest staranne dobieranie skryptów do kompilacji natywnej.
Aby monitorować rozmiar kodu natywnego poszczególnych funkcji i skryptów:
- Upewnij się, że znajdujesz się w widoku Serwera przez przycisk przełączania klienta/serwera.
- Wywołaj debug.dumpcodesize() z Command Bar.
W oknie Output zobaczysz łączną liczbę skryptów i funkcji, które zostały natywnie skompilowane do momentu wywołania, pamięć zajmowaną przez ich kod natywny 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, z funkcjami anonimowymi pokazywanymi jako [anonymous], a całymi skryptami jako [top level]. W ostatniej kolumnie procent oblicza się w stosunku do limitu rozmiaru kodu natywnego. Zauważ, ż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
Komputacja kodu do instrukcji dla konkretnego CPU wymaga dodatkowej pamięci do przechowywania. Ponadto optymalizacje dla złożonych funkcji mogą zabierać zbyt dużo czasu na wykonanie. Przekroczenie wewnętrznego limitu zgłasza błąd w oknie Output Studio, w tym:
Funkcja 'f' w linii 20 przekroczyła limit pojedynczego bloku instrukcji kodu
Ten błąd oznacza, że pojedynczy blok kodu wewnątrz funkcji użył więcej niż 64K instrukcji. Można to uniknąć, upraszczając funkcję lub dzieląc ją na pojedyncze 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 mapują się na bloki kontroli przepływu w twoim skrypcie, ale ten błąd można uniknąć, upraszczając kontrolę przepływu w funkcji lub dzieląc ją na pojedyncze 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 w sobie może mieć dużo instrukcji, lub limit mógł być 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 dla innych funkcji. Można także spróbować oznaczyć ten osobny skrypt --!native, ale 1 milion instrukcji zajmuje dużo pamięci i można 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 assemblera)
Czasami funkcja zawiera złożone fragmenty kodu, których kompilator kodu natywnego aktualnie nie może obsłużyć. Aby uniknąć tego błędu, zbadaj 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 ogólny limit pamięci dla danych kodu natywnego został osiągnięty. Aby tego uniknąć, spróbuj usunąć --!native z bardziej pamięciożernych skryptów, dzięki czemu więcej mniejszych skryptów zmieści się w limicie. Alternatywnie przenieś duże lub rzadko wywoływane funkcje do oddzielnego nienatywnego modułu.