Erlang

Posted by Nucc

A napokban újra előkapartam Joe Armstrong, Programming Erlang című könyvét, mert kicsit szerettem volna kizökkeni az imperatív nyelvek világából. Az Erlang, egy funkcionális nyelv, erről a fura fajról szeretnék pár sorban írni.

Az Erlanggal tavaly találkoztam, mikor is az OPM (Object Process Methodology) modellnek megfelelő felépítésű nyelvet kerestem. Az OPM egy egységes szerkezet-folyamat leírásra helyezi a hangsúlyt, az UML-ben leggyakrabban használatos szerkezeti diagrammal ellentétben. A szerkezet-folyamat alatt azt értem, hogy egy terven jelennek meg mind az állapotátmenetek, mind pedig az objektumok, melyek az átmenetekben részt vesznek. A folyamatok szemléltetésének van egy hatalmas előnye, mégpedig hogy vizuálisan is elkülönülnek egymástól a független állapotátmenetek, ezáltal a rendszert már az elejétől fogva párhuzamos folyamatokként tekinthetjük, ahol a szinkronázációs pontok (pl. shared object) azon objektumok lesznek, melyek több folyamatban is részt vesznek.

Az Erlang egy funkcionális nyelv, bár rálátásom szerint inkább gyengén funkcionálisnak nevezném. Az imperatív nyelvekben egy függvény értékét mindig az állapottér aktuális állapota határozza meg, így egy tetszőleges függvényt ugyanazokkal a paraméterekkel meghívva teljesen más eredményeket kaphatunk, ellenben a funkcionális nyelvekben szigorúan mindig ugyanazt. Ezen nyelveket inkább kutatásokra alkalmazzák, de egynéhány megjelent az iparban is, ilyen például az Erlang.

Az Erlangot mint írtam félig funkcionálisnak nevezném, ugyanis szekvenciális lefutás esetén (egy process egy szálon) funkcionális. Azonban az Erlang a párhuzamosságot célozta meg fő erényének, azon kívül, hogy gyönyörűen skálázható és igen hibatűrő. Mivel a párhuzamos programok - egész pontosan szálak - szinkronizáció során cserélnek információkat, ezért egy függvény eredményét befolyásolhatja egy másik folyamattal történő szinkronizáció eredménye. Az, hogy párhuzamos teljesen funkcionális nyelv létezhet-e, ezt inkább egy fórumbeszélgetésben boncolgatnám, de érzésem szerint nem.

A szálak futtatását a virtuális gép kezeli, így a szálak kezelése hatékonyabbá válhat, aminek megmagyarázáshoz kell írnom pár sort magáról a nyelvről.

Először is a többi nyelvben megszokott változó itt nem létezik, szerepüket konstansok váltják. Az elv a matemetikából ered, ahol ha azt állítom egy egyenletrendszer megoldásában, hogy x értéke 10, akkor bármely egyenletet tekintve az x értéke 10 lesz. Imperatív nyelveknél már nincs így, például ha veszünk egy számlálót, ami x értékét folyamatosan növeli, akkor ha a folyamatot tekintem, az x=x+1 már ellentmondásba kerülne, hisz nem tudunk olyan x-et mondani, mely kielégítené az egyenletet.  Az Erlang egyenletekkel dolgozik, nem pedig értékadásokkal. Merül fel a kérdés, hogy ha nincs változó, akkor mi van helyette? A válasz erre a függvény. Az előző példában szóbahozott számláló nem más, mint egy parciálisan rekurzív függvény. Például az 1-től n-ig számláló függény az az n hosszú  f(f(f(…f(0)))) függvénykompozíció, ami x > 0 intervallumon f(x+1) = f(x)+1, x = 0 esetén pedig f(0) = 0. Ekkor f(k) lesz az 1-től k-ig számláló függvényünk.

Amennyiben ennek részeredményeivel szeretnénk dolgozni, tegyük fel kiírni a képernyőre, úgy meg kell mondanunk, hogy miután megnövelte egyel az értéket, mit is tegyen az részeredménnyel. Erre szolgál a funkcionális nyelvekben használatos lambda kalkulus, ami segítségével egy függvényt paraméterként is átadhatunk, és kiértékelése majd egy általunk meghatározott ponton fog megtörténni a függvényben. Ha g(x) a kiirást végző függvény, akkor definiáljuk az f(x+1) = g(f(x)+1) egyenletet, ahol g az az identikus leképezés, mely továbbítja a függvényértéket a videókártya irányába (mondjuk elindítva egy másik folyamatot). Az új függvényünket úgy is írhatjuk, mint f(x+1, g ) := g(f(x,g) +1) ha x > 0, és f(0) = 0.

Milyen előnyökkel járhat, ha a konstansokkal dolgozunk? Párhuzamos környezetben a legnagyobb problémát az osztott változók, úgynevezett erőforrások okozzák. Biztosítanunk kell, hogy állapota mindig konzisztens maradjon, azaz például egyszerre csak egy folyamat módosítsa. Ez konstansok esetén nem okoz problémát, hiszen mindenki csak olvasni fogja. Azonban az erőforrások feladata, a szinkronizáció így nem valósulhatna meg, hisz nincs felület az információcserére.

Erlangban folyamatok létrehozása egy olcsó műveletnek számít, ezt a virtuális gép folyamatkezelőjével éri el (20000 folyamat/16ms). A folyamatok üzenetekkel kommunikálnak egymással. A folyamatokban ellenőrzőpontokat helyezünk el, melyhez egy várakozási sor, és őrfeltételek társulnak. A folyamat akkor haladhat tovább, ha a várakozási sorban lévő üzenetek valamelyikére érvényesül egy őrfeltétel. Amíg a blokkoltság fennáll, a folyamat állapota változatlan. Így ha a számlálós példát nézzük, a g függvény blokkolódjon mindaddig amíg nem kap egy üzenetet, és üzenet esetén pedig hívja meg rekurzívan önmagát úgy, hogy a számláló aktuális értékét reprezentáló konstanst növelje meg egyel. Mivel g is bárkinek üzenhet, így akár x aktuális értékét elküldheti üzenet formájában másoknak. Tehát mint látható, Erlangban az osztott változókat függvények veszik át, melyek folyamata bármikor megszakítható, és folytatható. A kommunikáció asszinkron, vagyis az üzenet elküldésével a küldő tovább fut, amíg nem terminál, vagy pedig blokkolódik.

Ez a fajta elgondolás előnye, hogy minden folyamat izoláltan fut, nem kell senkivel semmit megosztania. Ekkor viszont nem számít, hogy melyik processoron fut, továbbá az sem szükséges, hogy ugyanazon a gépen fusson ahol a többi szál. Ekkor igaz számításba kell venni a hálózati közeg sebességét (a programban szabályozhatjuk az elhelyezést), de a virtuális gépeket fürtbe szedve a folyamatokat bárhol elindíthatjuk a hálózaton, az üzenetküldést pedig a virtuális gép irányítja.

További előny, hogy imperatív nyelven megírt programoknál egy folyamat létrehozása költséges, és az operációs rendszer irányítja. Webszervereknél alkalmazzák például, hogy elindítanak 5-6 szálat, és minden, a kliens felől érkező kérést egy úgynevezett balancer valamelyik szálra tereli. Azonban problémát okozhat, ha a szerver hirtelen kap nagy terhelést. Ekkor új szálakat kéne létrehozni, ami költséges, ugyanakkor állandóan többet fenntartani pedig memóriaigényes. Erlang esetén mivel egy szál létrehozása olcsó, minden kérést külön szálra tehetünk, és akár kényelmesen újabb gépeket helyezhetünk szolgálatba bárminemű kódváltoztatás és külső eszköz (mások által megírt ütemező) nélkül.

Amennyiben érdekelnek a nyelv rejtelmei, látogass vissza később!
http://nucc.bteam.hu

OPM: http://www.slideshare.net/guest77b0cd12/object-process-methodology-presentation


2 Responses to “Erlang”

  1. agyvihar Says:

    Egyre több helyről hallani, hogy az Erlang-típusú nyelveké a jövő. Ahogy egyre nő a párhuzamosság, előtérbe kerülnek azok a nyelvek, amelyek nyelvi szinten biztosítják a párhuzamosságot explicit thread szinkronizáció nélkül.

    Az Amazon és a Facebook is futtat Erlangot tudomásom szerint, és a cloud computing terjedésével a kör csak bővülni fog. Szóval tanuljatok Erlangot, vagy hasonló nyelveket, ha készülni akartok a jövőre. :)

  2. bkil Says:

    Szép kis bevezető, és igen nagy okosságok vannak be. Igaz, ez a funkcionális dolog kicsit erőltetett… ;-) A gyengén funkcionális kifejezéssel viszont ki vagyok békülve. Mindketten tudjuk, hogy elég gyakoriak Erlangban a mellékhatások (és ezzel a hivatkozási helyfüggőség), mivel ez is egy tervezési elvük volt.

    Amúgy tényleg egyszerű és jól átgondolt kis nyelvecske, párhuzamosságra sokszor verhetetlen, bár a szintaxisa és itt-ott a rutinkönyvtára lehetne szebb, illetve lehetne valamiféle típusrendszere… Azért munkanyelvnek még elmegy. ;-) De mi lesz a többi szép, ipari funkcionális nyelvvel?! OCaml, Haskell, Scala, etc.?

Leave a Reply