Google åbner for Rust i Android

Illustration: Pixabay.com-bruger terimakasih0
Hukommelsessikker programmering er argumentet for mere Rust i styresystemet.

Google vil åbne for muligheden for at benytte Rust i Android-systemet. Det skriver Zdnet.

Rust er et system-programmeringssprog som C og C++, men med faciliteter som gør sproget hukommelsessikkert.

Mens hukommelsessikre sprog som Java og Kotlin gør det muligt at skrive sikre applikationer på platformen, består det underliggende system af kode skrevet i C og C++, og det her, at Rust bliver en ny mulighed, skriver Googles Android-udviklere Jeff Vander Stoep og Stephen Hines i et blogindlæg:

»Med C og C++ er udvikleren ansvarlig for styring af hukommelsens levetid. Desværre er det let at lave fejl, især med kompleks og flertrådet kode. Rust giver garantier om hukommelsessikkerhed, ved at bruge en kombination af tjek under kompilering, som håndhæver et objektets levetid og ejerskab, og tjek under kørsel, der sikrer, at tilgangen til hukommelsen er gyldig. Denne sikkerhed opnås samtidig med en ydeevne, som svarer til C og C++.«

Google finder, at halvdelen af de fejl, der handler om hukommelse, er mindre end et år gamle, og derfor giver det mening at benytte Rust til ny kode, i stedet for at skrive hele styresystemet om i Rust. Dertil kommer, at det ikke er praktisk muligt at omskrive alle de mere end ti millioner kodelinjer, som systemet udgør, ifølge udviklerne.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (9)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
#1 Michael Cederberg

Er der nogen der har erfaringer med Rust? Jeg har selv skrevet meget C/C++ kode og er ganske enig i at memory management er et issue. Relateret dertil er at en enkelt dårlig udvikler på et team kan smadrer alle andres produktivitet hvis hans fejl ikke opdages i tide. Pludseligt sidder alle og leder efter hans overskrivning af hukommelse som først opdages timer efter det er sket. I sprog som Java (øv) eller C# kan den slags problemer i meget højere grad containes.

Dder synes at være en Rust implementation til Arduino og det kunne være spændende at tage fat der. Alas, Arduino projekter når sjældent en størrelse hvor memory management er et problem.

  • 3
  • 0
#2 Peter Stricker

Er der nogen der har erfaringer med Rust?

Jeg har kun brugt det privat. Borrow Checkeren er meget nem at forstå. Og compileren har meget forståelige fejlmeddelelser med gode forslag til rettelser. Ud over borrowing har Rust et andet koncept der hjælper med memory safety, nemlig lifetimes. Det tog mig lidt mere tid at få styr på det.

Om Rust så er noget for dig, kan jeg ikke svare på. Men hvis du foretrækker statiske typer frem for dynamiske, så tror jeg at du vil være tiltrukket af Rust.

Arduino projekter når sjældent en størrelse hvor memory management er et problem

Det kræver ikke ret mange linjer C kode at skrive et program med "dangling pointer", "double free" og mange andre unoder der vil slå benene væk under den enkelte dårlige udvikler, du selv nævner. Der findes mange gode værktøjer til at hjælpe med at fange disse fejl, men de er ikke alle bygget ind i C compileren.

  • 3
  • 0
#4 Sune Marcher

Er der nogen der har erfaringer med Rust?

Jeg har desværre ikke haft ordentligt tid til at lave et hobbyprojekt, så er begrænset til at have læst The Crab Book og lave en del af opgaverne i Rustlings (JetBrains IntelliJ har et EduTools plugin hvor Rustlings er tilgængeligt, det er en ret fin måde at komme igang på).

Men ud fra det er mit indtryk af sproget rigtigt godt, det er klart det nyere sprog jeg har set der tiltaler mig mest – performance, sprogfeatures, build tool og packaging. Jeg har aldrig været fan af garbage collection, da det er snævert relateret til memory og ikke alle mulige andre resources, og mit indtryk er at lifetime+borrow er en meget bedre model.

Jeg har rodet lidt mere med Go, som også på mange måder er behageligt – jeg er fan af "vi er lidt kedelige mht. sprogfeatures, så kode er nem at gennemskue"... men synes at de til at starte med har været lidt for konservative (manglende generics og syntaktisk sukker for iterations, fx), og nogle steder er lidt for fanget i et C-mindset - og blandingen af at skulle tage stilling til pointers-eller-ej og have garbage collection er sådan lidt... bum bum. Plus error handling bliver meget verbose, og dependency håndtering har været meget præget af at Google bruger monorepos, fremfor hvad resten af os har brug for.

Rust lader til at addresere flere af de issues jeg har med Go, uden at ende i et komplekst monster som C++ (som jeg stadig holder meget af, selvom det måske har et element af Stockholm syndrom).

  • 1
  • 0
#5 Michael Cederberg

Jeg har aldrig været fan af garbage collection, da det er snævert relateret til memory og ikke alle mulige andre resources, og mit indtryk er at lifetime+borrow er en meget bedre model.

Nu er memory klart den mest allokerede resource, den mest complekse resource (når der er objecter i memory) og også en af de få hvor du kan ende med cykliske referencer o.lign. Derfor er der intet galt med at memory håndteres specielt.

Der er i øvrigt ofte en ide blandt folk der kommer fra en non-GC verden at GC er ineffektivt rent CPU mæssigt. Det er forkert i de fleste tilfælde. GC vil med tilstrækkeligt meget memory have betydeligt højere allokerings-throughput end traditionel memory management. Hvis ikke lige det var for de kedelige pauser som man kan få med GC så ville det være helt fint til næsten alt i moderne IT systemer.

  • 1
  • 0
#6 Sune Marcher

Nu er memory klart den mest allokerede resource, den mest complekse resource (når der er objecter i memory) og også en af de få hvor du kan ende med cykliske referencer o.lign. Derfor er der intet galt med at memory håndteres specielt.

Tjah, tjoh. Andre resourcer – sockets, files, threads, textures/bitmaps osv. - kan hurtigt koste mere at leake end memory, og du er nødt til at frigive dem korrekt. I GC sprog får du nemt noget miskmask med at være "ligeglad" med simple allokeringer, og mere eller mindre klodsede måder at håndtere andre resourcer... som måske kan gøres OK hvis de har rigtigt kort lifetime, men uden at du får noget forærende hvis der er brug for længere lifetime.

Hvis du kigger på fx moderne C++ smartptr, synes jeg ikke rigtigt at GC giver noget på den store mængde allokeringer med kort lifetime, og til længere lifetime giver det god mening at tage stilling til scope/ownership, om det så er simpel memory eller andre resourcer.

Rusts ownership model virker som et rigtigt godt designvalg for mig. Du kan så ikke lave fx cykliske referencer... med mindre du bruger unsafe blokke. Det vil dog typisk kun være nødvendigt i meget begrænsede dele af din kode (typisk på library niveau), hvor du kan fokusere en ekstra indsats, og dit client kode kan holdes safe, nemt at arbejde med, og compiler-verificérbar.

Og selvom du har GC er der alligevel situationer hvor du skal tænke over lifetime, hvis du vil undgå at putte unødigt (og nogle gange, latterligt højt) press på din allocator.

Der er i øvrigt ofte en ide blandt folk der kommer fra en non-GC verden at GC er ineffektivt rent CPU mæssigt. Det er forkert i de fleste tilfælde. GC vil med tilstrækkeligt meget memory have betydeligt højere allokerings-throughput end traditionel memory management. Hvis ikke lige det var for de kedelige pauser som man kan få med GC så ville det være helt fint til næsten alt i moderne IT systemer.

"It all depends" :)

GC er klart at foretrække frem for malloc/free-style håndtering, men det er jo ikke de to eneste muligheder der er. Jeg er ikke overbevist om at GC er den hellige gral, hverken i forhold til performance, ease of use eller korrekthed.

Der er ret mange forskellige GC typer, og på JVM'en kan du fx vælge imellem en del forskellige, og tweake dem. Yeah, du kan få allocs der er tosset meget hurtigere end typiske heap allocators i ikke-GC sprog, og du kan lave tradeoffs der gør at collection ikke gør så ondt... men der er overhead, intet er gratis.

GC fungerer "godt nok" til det meste. Selv indenfor JVM-verdenen er der dog fokus på at det er bloated – prøv fx at se hvad kombinationen af Quarkus og native compilation kan gøre for startup time og memory forbrug.

Og hvis ens sprogdesign nu gør at man ikke behøver så høj allocation throughput, fordi det meste kan leve på stack, man ikke behøver så meget bookkeeping overhead, og man er intelligent med memory layout (hvilket også forbedrer hastighed pga. locality of reference), well... :)

  • 0
  • 0
#7 Bjarne Nielsen

Tjah, tjoh. Andre resourcer – sockets, files, threads, textures/bitmaps osv. - kan hurtigt koste mere at leake end memory, og du er nødt til at frigive dem korrekt.

Minder mig om en oplevelse for mange år siden. Vores framework gav en grim advarsel, når programmet lukkede ned, hvis ikke vi havde deallokeret alt, hvad vi havde allokeret.

Jeg var henne og spørge om det nu også var nødvendigt, for hukommelsen ville alligevel blive frigivet, når programmet var lukket ned. "Hvis du ikke engang har styr på din hukommelse, har du så styr på dine andre ressourcer?" var svaret, og den lærestreg skrev jeg mig bag øret.

Og Rust kan jeg rigtigt godt lide, men det er, måske lidt uretfærdigt, blevet arkiveret som en løsning der leder efter et problem. I hvertfald for mig.

  • 1
  • 0
#9 Michael Cederberg

Tjah, tjoh. Andre resourcer – sockets, files, threads, textures/bitmaps osv. - kan hurtigt koste mere at leake end memory, og du er nødt til at frigive dem korrekt.

Så fokuser din indsats der. Der er ingen der siger at vi skal opfatte alle ressourcer ens. Du holder heller ikke styr på blokke på disken på samme måde som textures.

Hvis du kigger på fx moderne C++ smartptr, synes jeg ikke rigtigt at GC giver noget på den store mængde allokeringer med kort lifetime, og til længere lifetime giver det god mening at tage stilling til scope/ownership, om det så er simpel memory eller andre resourcer.

Jeg er ikke ude i et korstog mod C++. Jeg har skrevet C/C++ kode i 35 år og C++ i 25 år. Dog ikke særligt meget de sidste 8 år men jeg har fint fulgt med i udviklingen. Der er stadigvæk mange muligheder for at ødelægge memory i C++. Derfor Rust.

Det vil dog typisk kun være nødvendigt i meget begrænsede dele af din kode (typisk på library niveau), hvor du kan fokusere en ekstra indsats, og dit client kode kan holdes safe, nemt at arbejde med, og compiler-verificérbar.

Helt enig. Og det er essentielt.

Og selvom du har GC er der alligevel situationer hvor du skal tænke over lifetime, hvis du vil undgå at putte unødigt (og nogle gange, latterligt højt) press på din allocator.

Helt enig. Men det er typisk meget nemmere. Jeg har bygget near realtime systemer i C# og der er man nødt til at smide C# lærebogen væk fordi det er en helt anden måde at tænke på. Men som du skrev ovenfor, så er det kun en ganske lille del af koden hvor man er nødt til at tænke på den måde. Og i libraries kan man endda træde udenfor GC og bruge raw memory.

Forskellen er at i en GC verden vil kode som en udvikler laver sjældent kunne trampe på memory en anden udvikler laver. Der er mange andre muligheder for at dumme sig, men ovenståtende giver meget højere produktivitet for både den ringeste udvikler og stjernen.

Der er ret mange forskellige GC typer, og på JVM'en kan du fx vælge imellem en del forskellige, og tweake dem. Yeah, du kan få allocs der er tosset meget hurtigere end typiske heap allocators i ikke-GC sprog, og du kan lave tradeoffs der gør at collection ikke gør så ondt... men der er overhead, intet er gratis.

Mjaaa ... tjaa. Hvis man kan leve med pauser og har nok memory så vil GC normalt altid være mere effektivt end traditionel memory management.

Ekstremerne er:

  • Hvis man har uendeligt meget memory så skal man aldrig lave GC og så er memory management i praksis gratis.
  • Hvis man kun har en byte mere end max working set så vil GC typisk være elendigt.

Omkostningerne ved allokering i en GC verden er typisk tæt ved 0. Omkostningerne ved GC afhænger af hvor mange objekter der overlever. Jo længere der går mellem GC, jo færre objekter overlever. Jo mere memory jo længere mellem GC. Jo mere memory, jo tættere på gratis memory management.

Ja der er alle mulige eksotiske metoder at lave GC på, men ovenstående holder for alle jeg kender. Traditionel memory management opfører sig på en helt anden måde.

Og hvis ens sprogdesign nu gør at man ikke behøver så høj allocation throughput, fordi det meste kan leve på stack,

Enig. Af samme grund hader jeg Java af et godt hjerte. Der ligger dog nogle optimeringer i JVM der laver mange heap allokeringer om til stak allokeringer.

Jeg var henne og spørge om det nu også var nødvendigt, for hukommelsen ville alligevel blive frigivet, når programmet var lukket ned. "Hvis du ikke engang har styr på din hukommelse, har du så styr på dine andre ressourcer?" var svaret, og den lærestreg skrev jeg mig bag øret.

Tjaa. Det giver også god mening i en verden hvor memory skal styres. Fx. betyder det at man i højere grad kan opfatte programmet som legoklodser der kan kombineres. Men der er ingen grund til at programmøren styrer noget der ikke behøver styres. Du styrer heller ikke spændingen på CPU'en, retransmission af TCP pakker, etc. Jo mere vi kan fjerne fra programmørens bekymringer uden at det giver problemer, jo mere hjernekapacitet kan han bruge på ting der giver værdi. Resource management giver sjældent værdi men kan være nødvendigt alt efter programmeringsmodel.

  • 1
  • 0
Log ind eller Opret konto for at kommentere