Przeglądałem ankietę zorganizowaną przez Stack Overflow w tym roku i zaciekawiły mnie wyniki na temat najbardziej lubianych języków wśród grupy 71467 osób. Ciekawy jestem czy ten język jest faktycznie aż tak lubiany i dlaczego. No i jak sprawuje się w świecie "embedded".
8a94ea75-756d-43c7-bb26-7233f7b0035d
m_h

Z mojej perspektywy: Syntax prostszy niż c++ ale lifetime Checker potrafi być mocno upierdliwy. Jeżeli chodzi o embedded, pisałem tylko na cortexy m oraz r, wydajnościowo z c nie widzę różnicy.

Femto

Jestem programistą embedded i miałem 3 podejścia do Rusta (1 hobbystycznie i 2 w firmie). Wszystkie nieudane. Rust ma bardzo ciekawe założenia, które podnoszą niezawodność kodu, bardzo dobrą dokumentację i w bogaty sposób tłumaczy błędy kompilatora. Za te rzeczy programiści go kochają. Ale zdecydowanie brakuje mu początkowej niszy i specjalizacji zastosowania.


Embedded to bardzo szeroka dziedzina. Podzielmy ją więc na mniejsze części:

  • bare metal na niewielkich rdzeniach pokroju ARM M0. Tutaj 30-70% kodu do pisanie po rejestrach MCU, a Rust wymaga by bypassować jego mechanizmy bezpieczeństwa i pożyczania zmiennych. Kod jest dużo bardziej skomplikowany niż w C i nie oferuje dużo więcej. Próg wejścia dla początkujących jest znacznie wyższy niż w C (trzeba rozumieć zaawansowane koncepcje języka Rust tylko po to by je obejść by wpisać pod adres pamięci wartość bez nadzoru...)

  • małe procki z RTOSami (jak ARM M0-M7). W projektach zorientowanych na prędkość developmentu FW używa się gotowych sterowników i RTOSów kosztem zasobów/ceny hardware. Dla Rusta nie istnieją póki co tak rozbudowane i stabilne biblioteki, które pozwoliłyby w pełni wykorzystać tę ścieżkę. Programista który zna FreeRTOSa i dany ekosystem musi poświęcić bardzo dużo by przełączyć się na Rusta. Nikogo na to nie stać.

  • aplikacje z Linuxem... Jeżeli robisz w Kernel Space jesteś skazany na C. Jeżeli robisz w User Space... To tak naprawdę możesz stworzyć oprogramowanie w dowolnym języku programowania. Poza ograniczonymi zasobami pisanie nie różni się mocno od pisania na PC z Linuxem. A więc Rust musi tutaj konkurować z C++, Java, Python, JS Node itd.


Czego potrzebuje Rust? Tak jak już pisałem początkowej specjalizacji. Gdyby Rust posiadał wyjątkowo dobre narzędzia do np. tworzenia backendów www (jak Node / Python), tworzenia aplikacji GUI (jak Node + Electron), pozwalał w łatwy sposób automatyzować rzeczy (jak Python), pozwalał w łatwy sposób pisać AI / robić modele matematyczne (jak Python) to miałby szanse mocno rozwinąć się w swojej niszy, zdobyć popularność i eskalować na inne dziedziny. Obecnie musi konkurować z C/C++ którego zaletą jest "naucz się tego języka, a zrobisz w nim wszystko od serwera, przez grę po stację kosmiczną".


To co osobiście obserwuję to stopniowe wprowadzanie C++ do low level embedded. Biblioteki standardowe są tam tak przerobione by alokować pamięć statycznie i poza zaleceniami by unikać funkcji wirtualnych można korzystać z wielu dobrodziejstw tego języka.


Ps. Wiem że mówi się o wprowadzeniu Rusta do Kernela Linuxa ale moim zdaniem to błąd. Już teraz pisanie w Kernel Space ma bardzo wysoki próg wejścia m.in. przez dług technologiczny i brak dobrej dokumentacji (kiedyś nazywało się to open firmware a teraz device tree? wymieszaliśmy nazwy z obu podejść? chcesz się dowiedzieć jak to działa? wal się, w dokumentacji dt damy 2 niezrozumiałe przykłady i starczy). Rust sprawi, że pisanie driverów na linuxa będzie jeszcze trudniejsze.

warzone

@Femto dzięki za komentarz.

Miałem kiedyś okazję pracować w miejscu, gdzie stosowano C++ razem z minimalistycznymi bibliotekami standardowymi, ale nieraz się pamięć przepełniała.


Nawet nie chce mi się wyobrażać kiepskiej architektury w Ruście. Chyba bym się od razu zwolnił.


C dobry jak witamina.

inskpektor

@Femto O, fajnie że się podzieliłeś doświadczeniem. Też kiedyś hobbystycznie próbowałem rust ale było to 6-7 lat temu. Jednak pamiętam że, że tak powiem 'pobawienie' się tym językiem było już trudne bo kompilator łapał za gardło :). Od tego czasu pewnie sporo się zmieniło na lepsze.

Femto

@warzone Zarówno C jak i C++ to języki konstruowane według zasad "nie płacisz za to z czego nie korzystasz". To znaczy, że z jednej strony są bardzo wydajne (nie robią nic ponad to o co je poprosisz), a z drugiej możesz sobie stworzyć pusty pointer i wskazuje on na losowy adres pamięci. Inicjalizacja takiego pointera przez kompilator to praca której nie wszyscy potrzebują i tyle .


Z C++ w embedded jest problem jak z piłami łańcuchowymi. Ekstremalnie skutecznie przecinają zarówno drewno jak i kończyny. Nieprzeszkolony operator szybko się potnie przez co łatwo powiedzieć, że "ręczna piła dużo lepsza bo jeszcze nic sobie nią nie uciąłem".


Niestety ani uczelnie ani podręczniki nie skupiają się na np. tym jak malloc/new, free/delete, biblioteka standardowa itp. działają pod maską i niemal wszyscy jesteśmy tymi nieprzeszkolonymi operatorami. Śledzenie pamięci i jej fragmentacji mogłoby zjeść pół miejsca na kod w takim MCU z 32kB flesha i często free() nawet nie jest zaimplementowane...


Ja mam zasady które stosuje po kolei w zależności od konieczności:

  • alokuj tylko statycznie (95% przypadków)

  • jak się nie da alokuj dynamicznie ale dokładnie RAZ (np. w zależności od konfiguracji urządzenia jeden bufor może być większy, a drugi mniejszy. Alokuje je na starcie i nie ruszam.

  • alokuj dynamicznie chunki ale tylko o jednej z 1..n znanej wielkości. Wtedy sensownie łatwo jest zaimplementować śledzenie fragmentacji. Koszty testów takiego oprogramowania to od razu x2 albo x3.

Zaloguj się aby komentować