Rust umożliwia parametryzacje optymalizacji Release poprzez odpowiednie wpisy w Cargo.toml oraz config.toml

Takimi wpisami są w Cargo.toml np:

[profile.release]
opt-level = 3
debug = false
lto = "fat"
panic = "abort"

gdzie:

  • opt-level – ozacza poziom optymalizacji LLVM, odpowiednik -Ox
  • debug – oznacza czy mają być metadane debug czy nie, nie wpływa na wydajność ale na rozmiar
  • lto – sposób linkowania bibloteki, fat daje nam większe możliwości optymalizacji naszego kodu i inlinowania
  • panic – w przypadku wersji abort oznacza, że program nie używa cacha do obsługi błędów, więc działa jak noexcept w C++ przez co działa szybciej

W pliku $PROJECT_HOME/.cargo/config.toml

Można dodać taki wpis:

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = "--emit=llvm-ir"

gdzie flaga --emit kompiluje nam do LLVM instruction przez co kompilator LLVM może lepiej zoptymalizować nasz kod

Mamy jeszcze do dyspozycji optymalizacje kodu poprzez profilowanie, coś jak JIT w JVM

A więc co musimy zrobić, żeby uruchomić aplikację w najbardziej wydajnej wersji?

Na początek instalujemy LLVM w wersji 11+, opis dla Debian/Ubuntu: https://apt.llvm.org/

Następnie w pliku: $PROJECT_HOME/.cargo/config.toml modyfikujemy wpis na:

rustflags = "--emit=llvm-ir -Cprofile-generate=/tmp/profdata"

Następnie kompilujemy w wersji release i przechodzimy wielokrotnie ścieżki programu, operacje które są głównie wykonywane podczas działania programu. Jak już skończymy, możemy zakończyć program i wykonać:

llvm-profdata merge -output=/tmp/profdata/rustc-llvm.profdata /tmp/profdata/*.profraw

Czyli połączyć nasze pliki profilu w jeden duży plik profilowy z działania aplikacji

Ostatnim krokiem jest zmiana w pliku: $PROJECT_HOME/.cargo/config.toml

rustflags = "--emit=llvm-ir -Cprofile-use=/tmp/profdata/rustc-llvm.profdata"

oraz kompiacja. Czyli LLVM optymalizuje nam kod pod operacje które wcześniej wykonaliśmy, aplikacja działa szybciej 🙂

Niestety przy każdej zmianie trzeb te operacje powtarzać jeśli chcemy mieć najwydajniejszą wersje naszej aplikacji

Test mojej wersji vertx:

Dark Mode

vertx-rust (this link opens in a new window) by kathog (this link opens in a new window)

Simple Rust version of vertx tcp eventbus, tcp server using zookeeper cluster manager

Bez optymalizacji:

[nerull@anvil vertx-rust]$ wrk -d 10s -t 5 -c 500 http://127.0.0.1:9091/
Running 10s test @ http://127.0.0.1:9091/
  5 threads and 500 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.23ms    1.30ms  38.75ms   74.01%
    Req/Sec    44.90k     2.71k   56.82k    74.20%
  2236733 requests in 10.07s, 258.11MB read
Requests/sec: 222083.80
Transfer/sec:     25.63MB
[nerull@anvil vertx-rust]$

A teraz efekt po optymalizacji:

[nerull@anvil vertx-rust]$ wrk -d 10s -t 5 -c 500 http://127.0.0.1:9091/
Running 10s test @ http://127.0.0.1:9091/
  5 threads and 500 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.00ms    1.28ms  24.46ms   78.23%
    Req/Sec    49.76k     4.99k   86.04k    77.20%
  2479491 requests in 10.04s, 286.12MB read
Requests/sec: 246883.21
Transfer/sec:     28.49MB
[nerull@anvil vertx-rust]$

Jak widać wzrost jest na poziomie ~11%

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *