← Takaisin
Julkaistu 2019-03-11 · Jarkko Vainio

Rust-ohjelmointikieli – C:n ja C++:n korvaaja?

Rust lupaa turvallisemman ja yhtä suorituskykyisen vaihtoehdon C:lle ja C++:lle. Onko lupaus todellinen?

Rust-ohjelmointikieli – C:n ja C++:n korvaaja?

Törmäsimme sattumalta jokin aika sitten uudehkoon ohjelmointikieleen nimeltä Rust. Aluksi se vaikutti liian hyvältä ollakseen totta, joten päätimme ottaa selvää miten asia on. Kielen kehittäjät antoivat suuria lupauksia siitä millainen Rust on ja mitä sillä pystyy tekemään. Ehdottomasti suurin väite oli että Rust on turvallisempi ja yhtä suorituskykyinen kuin C ja C++. Rustin ominaisuuksien ja kielen suunnitteluperiaatteiden luvattiin korjaavan lähes kaikki näiden kielien ongelmat.

Tämä kirjoitus on suunnattu teknisesti orientoituneille johtajille, projektipäälliköille sekä ohjelmistoarkkitehdeille. Kirjoituksen lähdeteoksena on käytetty The Rust Programming Language -kirjaa, ellei toisin ole mainittu.

Ferris-rapu on Rust-ohjelmointikielen epävirallinen maskotti, joka seikkailee myös The Rust Programming Language -kirjassa.

C ja C++

C ja C++ ovat järjestelmäohjelmointikieliä. Niillä pystytään tekemään ohjelmistoja sulautetuista järjestelmistä, joissa on tiukat reaaliaikavaatimukset, aina raskaisiin työpöytäohjelmistoihin, joiden pitää pystyä prosessoimaan monimutkaisia operaatioita. Webin puolelle C ja C++ eivät ole vielä juuri levinneet, koska niiden turvallinen käyttö vaatii merkittävästi erityisosaamista. Nämä kielet mahdollistavat hyvin erikoisten ja vaikeasti selvitettävien ongelmien syntymisen, jos niitä käyttävät ohjelmoijat eivät ole tietoisia niihin liittyvistä vaaroista ja eivät jatkuvasti arvioi tekemäänsä koodia näiden vaarojen suhteen. Tällaiset vaarat liittyvät esimerkiksi muistinhallintaan ja rinnakkaisuuteen.

Rustin historia ja nykytila

Rust-ohjelmointikielen kehitys alkoi vuonna 2006 Mozilla-yhteisössä, joka kehittää myös Firefox-selainta. Rust on käännettävä ohjelmointikieli, samaan tapaan kuin C ja C++. Rust kehitettiin alunperin korjaamaan Firefox-selaimessa olevia rinnakkaistushaasteita. C++-kielellä kirjoitetun Firefox-selaimen toiminnan jatkuvasti lisääntyvä rinnakkaisuus oli muodostunut niin haastavaksi kokonaisuudeksi, että parhaaksi ratkaisuksi nähtiin kehittää kokonaan uusi ohjelmointikieli tekemään rinnakkaistuksesta yksinkertaisempaa ja turvallisempaa. Rustin kehitys levisi hyvin nopeasti myös Mozillan ulkopuolelle, ja nykyisin Rust-kielen kehittäjistä suurin osa on Mozillan ulkopuolella. Kielen ympärille on kehittynyt kukoistava ekosysteemi.

Nykyään Rust-kieli on jo verrattain laajasti teollisuudessa käytössä ollakseen vielä niin tuore keksintö. Mainittakoon esimerkiksi että Dropbox-pilvitiedostopalvelu ja NPM-paketinhallintajärjestelmä käyttävät Rustia.

Tärkeimmät tekniset hyödyt ja haasteet

Kuten aiemmin mainittiin Rust korjaa C ja C++-kielien pahimmat ongelmat, ja voisi potentiaalisesti jopa korvata ne kokonaan. Nämä kielet tosin ovat niin laajasti käytössä etteivät ne kokonaisuudessaan ole mihinkään katoamassa.

Turvallinen muistinhallinta ilman roskienkeruuta. Rust käyttää niin sanottua omistajuusmallia, jonka avulla huolehditaan siitä että muistissa oleva data on olemassa sen ajan kun sitä tarvitaan, ja sen jälkeen varattu muisti vapautetaan automaattisesti. Tällä mallilla ehkäistään sekä muistin korruptoituminen (memory corruption), jossa muistissa oleva data ei olekaan mitä sen pitäisi olla, sekä muistivuodot (memory leak), jossa muistissa oleva data jää vapauttamatta ja pahimmassa tapauksessa käytettävissä oleva muisti loppuu kesken.

Turvallinen rinnakkaisuus. Omistajuus- ja lainausmallien yllättävänä hyötynä on myös rinnakkaisuusongelmien eliminoituminen. Lainausmalli määrittää miten muistissa olevaan dataan voidaan viitata. Nämä kieleen sisäänrakennetut mekanismit estävät tilanteen jossa yksi säie ylikirjoittaa toisen tekemät muutokset jaettuun muistiin – molemmat eivät voi kirjoittaa samanaikaisesti samaan dataan rikkomatta lainaussääntöjä, joiden noudattamista kääntäjä valvoo automaattisesti.

Ferris ihmettelee miksei koodi käänny

Tehokkuus. Rust vertautuu tehokkuudeltaan C ja C++ -kieliin, tietyissä tapauksissa ollen jopa nopeampi kuin C++. Rust käyttää niin sanottua Zero Cost Abstraction -mallia, jolloin korkean tason kielistä tuttujen ominaisuuksien käyttämisestä ei seuraa ajoaikaista tehokkuushaittaa, vaan käännöksen yhteydessä ohjelmointityötä helpottava abstraktio eliminoituu pois. Rustin suurin heikkous on tällä hetkellä hitaahko käännösaika, joka kuitenkin vertautuu C++-ohjelmaan jossa on käytetty useita templateja.

Matalan tason hallinnan ja korkean tason käyttömukavuus. Rust on erittäin ilmaisuvoimainen ja siihen on kerätty syntaksiltaan parhaat ominaisuudet, joita muut kielet tarjoavat. Kielen syntaksi muistuttaa monelta osin C++11/14:ta, mutta siinä on myös lisäksi uusimmista JavaScript-versioista (ES6) tuttuja mekanismeja.

Elinaikamerkinnät (lifetime annotations). Merkittävin Rust-ohjelmointia omalta osaltaan hidastava syntaksiero muihin ohjelmointikieliin nähden. Rust-kääntäjä analysoi muistissa olevan datan olemassaoloajat käännösaikana, mutta se ei kaikissa tilanteissa pysty päättelemään onko jokin data olemassa riittävän pitkään. Tämän vuoksi ohjelmoija joutuu välillä opastamaan kääntäjää merkitsemällä elinaikamerkinnöillä muuttujien olemassaoloaikoja.

Cargo-paketinhallintajärjestelmä. Cargo toimii samaan tapaan kuin NPM webbimaailmassa, ja hoitaa vielä samalla cmake:n tehtävät automatisoimalla käännöksen tekeminen. Lisäksi Cargossa on sisäänrakennettu dokumentaatiotyökalu.

FFI-rajapinta. Rust-ohjelmakoodissa voidaan käyttää olemassa olevia C-kirjastoja FFI-rajapinnan kautta (Foreign Function Interface). Tämä auttaa hyödyntämään valtavaa määrää olemassa olevaa toiminnallisuutta, eikä kirjastoja tarvitse kääntää Rust-kielelle.

Unsafe-lohkot. Rust mahdollistaa myös sen turvamekanismeista poikkeamisen tarvittaessa. Unsafe-avainsanalla voidaan tehdä koodilohkoja, joissa voidaan nimensä mukaisesti suorittaa epäturvallista koodia. Tämä on olennainen ominaisuus, joka mahdollistaa liitynnät epäturvalliseen maailmaan Rustin ulkopuolella, kuten laitteistoon.

Ferris ei tykkää Unsafe-koodilohkoista

Liiketoimintahyödyt

Microsoft julkaisi helmikuussa 2019 tutkimuksen, jonka mukaan 70% kaikista Microsoft-tuotteiden tietoturva-aukoista johtuu muistinhallintaan liittyvistä ongelmista. Juuri siis niistä ongelmista, jotka Rust ratkaisee ilmaiseksi.

Tässä on syytä huomata ettei kyse ole pelkästään potentiaalisista tietoturva-aukoista, vaan kyse on täysin todellisesta ajasta joka käytetään debuggaamiseen, eli ohjelmointivirheiden tutkimiseen. Muistinhallinnasta ja rinnakkaisuudesta aiheutuvat ongelmat ovat häijyimpiä ongelmia, mitä ohjelmistokehityksessä voi tulla vastaan. Useamman kerran on allekirjoittaneelle C++-kielen kanssa tullut tilanne vastaan, jossa on tarvinnut käyttää useampi viikko puhtaasti tällaisen virheen selvittämiseen. Korjaus yleensä hoituu muuttamalla paria koodiriviä, mutta tällaisen ongelman syyn selvittäminen on tuskaista. Rust on suunniteltu siten, että tältä työltä vältytään kokonaisuudessaan, eikä siitä hyödystä tarvitse maksaa esimerkiksi hitaammalla koodintuotto- tai ohjelman suoritusnopeudella.

Refaktoroidako kaikki mahdollinen?

Käänteentekevä uusi teknologia herättää aina myös kysymyksen kannattaako nykyjärjestelmiä korvata uudella teknologialla. Yleisohjeena voidaan sanoa, että hyvin toimivia ja järjellisellä työllä ylläpidettävissä olevia järjestelmiä ei kannata uudelleenkirjoittaa. Älä korjaa, jos se ei ole rikki. Sen sijaan uudet ominaisuudet kannattaa kehittää uusilla teknologioilla ja rikkinäisten vanhojen järjestelmien korvaamista kannattaa vakavasti harkita.

Yksi Rustin vahvuuksista on se että sillä voidaan korvata yksittäisiä osia muilla ohjelmointikielillä kirjoitetuista ohjelmistoista FFI-rajapinnan avulla. Rustilla kirjoitettu komponentti liitetään osaksi muuta ohjelmistoa, joka tarvittaessa kutsuu Rust-komponentin funktioita suoraan toisen ohjelmointikielen puolelta. Tällöin kysymys ei ole siitä että koko olemassa oleva järjestelmä tarvitsisi kirjoittaa uusiksi jotta Rustin tarjoamiin hyötyihin päästään käsiksi, vaan käyttöönotto on yksinkertaista ja turvallista.

Yhteenveto

Rust on hyvin mielenkiintoinen verrattain uusi ohjelmointikieli, jolla on hyvä potentiaali korvata C ja C++ -kielien käyttö erityisesti uudessa kehityksessä ja vanhojen järjestelmien jatkokehityksessä. Rust tarjoaa monenlaisia moderneja etuja vanhoihin ja vaarallisiin kieliin verrattuna.

Rustacean

Aiheeseen liittyviä kirjoituksia