Skriv ut
ImageErlangprogrammerare kan lugnt ignorera revolutionen med multikärnor och fortsätta jobba som förut. Erlangkod blir automatiskt parallell.
Kenneth Lundin har arbetat med programvaruutveckling i nära 30 år. Han har erfarenhet av utveckling på ett flertal operativsystem och i olika språk som Plex, Pascal, C++, Java och Erlang. Han har arbetat med utveckling av Erlang och dess omfattande programbibliotek (OTP) de senaste 10 åren och är nu sedan flera år ansvarig för utvecklingen av Erlang och OTP på Ericsson.
På 1990-talet lärde vi oss att hantera objekt. Omvandlingen från strukturerad programmering till objektorienterad programmering var den största förändringen de senaste 20, kanske 30 åren. Det har skett andra förändringar men inga så fundamentala.

Erlang-kod-komplett I Erlang är parallellism inbyggt i språket. På en multikärna körs Erlangs processer i olika kärnor. OBS! Klicka för att se hela källkodsexemplet.
 
Provkörning av källkodsexemplet. Ping och Pong studsar theBall mellan sig tre gånger. Ping servar:
pingpong:start().
Pong received the ball
Ping received the ball
Pong received the ball
Ping received the ball
Pong received the ball
Ping received the ball
Ping finished
Pong finished
 
Överkurs:
Så stöder man multikärnor i en EVM

Erlangs virtuella maskin (EVM) exekverar som en operativsystemstråd. I en enkärnig processor använder EVM en ensam schemaläggare som fördelar exekveringstiden mellan sina Erlangprocesser. I praktiken är det då bara en Erlangprocess som exekverar åt gången.

I en EVM med stöd för Symmetrical Multi Processing (SMP) krävs flera schemaläggare som exekverar parallellt i varsin OS-tråd. Om operativsystemet fördelar exekveringen av trådarna över flera processorkärnor, får Erlang äkta parallellitet.

De flesta populära operativsystem stödjer idag trådar och SMP. Erlangs virtuella maskin EVM är skriven i C och körs som en OS-process. Den består av 1 till N schemaläggare som exekverar som en OS tråd inom OS-processen.

Trådarna delar minne. För att de inte ska störa varandra när de uppdaterar gemensamma datastrukturer används olika typer av mekanismer för synkronisering:
  • Spinnlås som loopar tills låset blir tillgängligt.
  • Atomära operationer som säkerställer att ett helt CPU-ord uppdaterats som en oavbruten operation.
  • Mutex - kodregioner som endast kan beträdas av en process i taget.
KL
 
Image
 
Image
Prestanda för olika antal schemaläggare på en åttakärnig arkitektur (två fyrkärniga Xeonprocessorer). Maxprestanda erhålls vid lika många schemaläggare som kärnor.
 
Image
Utöver Ericsson utvecklar Telia Sonera, T-Mobile, Nortel och många andra företag över hela världen produkter med hjälp av Erlang. Alla dessa kan nu få ökade prestanda – utan portering – på de nya multikärnorna.
 
Idealt språk för telekom

Historien om Erlang startade under mitten av åttiotalet då Computer Sciencelaboratoriet på Ericsson experimenterade med programmeringstekniker och språk för telefonisystem.

Man behövde språk med bra stöd för utmaningar i telekomsystem:
  •  parallella förlopp, som när flera ringer samtidigt
  •  felisolering - ett fel i ett telefonikoppel skall inte drabba övriga koppel
  •  non-stop: felrättningar och funktionstillägg måste kunna göras under drift
 Erlangprogram kompileras normalt - precis som Java - till ett processoroberoende format som exekveras av en virtuell maskin, en EVM (Erlang Virtual Machine). Man kan även kompilera till maskinkod, eller kombinera. EVM:er finns bland annat till Unix, Linux, Windows, VxWorks och Mac OSX.

Stödet för skalbara lättviktsprocesser är inte det enda speciella med Erlang. Programmen är korta och läsbara eftersom språket är deklarativt, har hög abstraktionsnivå, mönstermatchning och automatisk effektiv minneshantering. Språket stöder mjuk realtid med svarstider på millisekundnivå och kod kan bytas under drift.

Lättviktsprocesserna utbyter data endast genom meddelandesändning vilket gör att fel inte sprider sig. Språket har enkla och konsistenta felåterhämtningsmekanismer. Processer kan skicka meddelanden till processer på andra datorer - ur programmerarens synvinkel är detta transparent. Det går också att skicka meddelanden till C- och Javaprogram som om de vore Erlangprocesser.

Även om maskinoberoende Erlang är tillräckligt snabbt för de flesta tillämpningar kan det i vissa sammanhang vara intressant att ytterligare optimera utvalda delar av koden.

För detta finns kompilering till native kod. Denna teknik är utvecklad av HiPE-gruppen (High Performance Erlang) på Uppsala Universitet. Stöd finns för PPC, x86, ARM, Sparc. Även denna teknik stödjer SMP eftersom den exekveras av Erlangs VM där stödet för SMP ligger.
KL
Förrän nu, när processorerna blir multikärnor.

Nu är prestanda inte gratis längre. Naturligtvis kommer det fortfarande att finnas generella prestandavinster som alla kan utnyttja främst tack vare utökningar av cacheminnets storlek. Men om du vill att din applikation skall kunna dra fördel av den fortsatta exponentiella prestandaförbättringen hos nya processorer så behöver din applikation vara parallell.

Vilket är lättare sagt än gjort. Dels kan programmen behöva skrivas om från grunden, dels är det svårt att skriva parallella program i traditionella programmeringsspråk.

För de flesta programmerare som använder C, C++ eller Java är hantering av multitrådning någonting nytt. Eller så är det något man försökt undvika eftersom det är svårt och ger upphov till nya problemställningar. Det är dessutom svårt att hitta källan till de fel som kan uppstå.

När man däremot programmerar i Erlang är allt som vanligt. Man ställs inte inför några nya problem. Detta eftersom majoriteten av alla Erlangprogram redan är parallella. De flesta Erlangprogram kan dra fördel av multikärnor och SMP direkt, de behöver inte ens kompileras om.

Det naturliga sättet att programmera i Erlang är att dela upp lösningen i Erlangprocesser som representerar olika företeelser i ett system. I ett telekomsystem kan det till exempel vara naturligt att ha en process per part i ett telefonikoppel eller att representera varje aktiv påslagen mobiltelefon med en process. Man får på så sätt en isolering av data så att eventuella fel i hantering av ett koppel inte påverkar andra koppel negativt.

Man får dessutom den parallellitet som behövs.

Det här sättet att programmera har direkt stöd i språket. Det är en av Erlangs stora styrkor och därför används det i stort sett överallt där produkter utvecklas i Erlang.

I ett stort system kan Erlangprocesserna uppgå till 10 000-tal och man inser lätt att detta inte hade fungerat med vanliga operativsystemprocesser eller -trådar.

Erlangs processer är däremot extremt lättviktiga. En EVM kan hantera miljontals Erlangprocesser.

Erlang exekveras i en virtuell maskin (EVM) som ur operativsystemets synpunkt är en process.

I en EVM finns en eller flera schemaläggare som har hand om exekveringen av Erlangprocesser och I/O-jobb. Antalet schemaläggare är konfigurerbart vid uppstart av EVM och varje schemaläggare körs som en OS-tråd.

OS:et ansvarar för att distribuera exekveringen för olika trådar på processorkärnor eller processorer i ett SMP-system.

Fördelarna med denna lösning är att den är oberoende av både processorarkitektur och operativsystem. Det enda man behöver göra är att använda parallella Erlangprocesser - och det är redan det normala sättet att använda Erlang.

Applikationsprogrammeraren som använder Erlang kan inte och ska inte göra processorspecifika optimeringar, för då försvinner en av styrkorna med Erlang - portabiliteten. Vidare behöver man inte veta om man kör på 1, 2, 4, 8 eller fler kärnor - man kan ha samma logik i Erlang oavsett antalet kärnor.

I EVM - som skrivs i C - kan det finnas processorspecifika optimeringar bland annat med låsfunktioner skrivna i assembler. Men EVM är inte specifik per processor utan bara per processorfamilj med kompatibelt instruktionsformat.

Vi försöker undvika processor- och operativsystemspecifika lösningar i det längsta eftersom det skapar mycket extra arbete med underhåll och test.

Man är förstås också beroende av att SMP har ett effektivt stöd i operativsystemet. Men detta verkar i praktiken inte vara något problem för till exempel Linux, Solaris, Windows eller andra moderna operativsystem.

Det enda som Erlangprogrammeraren behöver tänka på, för maximal prestanda i en multikärna, är att ha minst lika många Erlangprocesser redo att köra, som det finns processorkärnor.

Om exempelvis ett system med många processer skickar all information via endast en process kan denna lätt bli en flaskhals.

För att få en uppfattning om den verkliga prestandan för Erlang på multikärnor, har vi gjort mätningar på olika processorarkitekturer och olika operativsystem.

Mätningar har gjorts på ett flertal olika system med flerkärninga processorer:
På alla dessa system visar mätningarna att Erlang program kan dra
nytta av flera kärnor.

I diagrammet intill visas resultatet av tester körda på en standardserver från HP (Proliant DL140G3) som är bestyckad med två fyrkärniga 1,6 GHz Intel Xeon 5310.

Operativsystemet är Suse Linux Enterprise Server 10 x86-64.

Testprogrammet består av 16 Erlangprocesser som var och en kör avkodning respektive kodning av komplexa protokollmeddelanden typiska för tele- och datakommunikation. Mätetalet är antalet meddelanden som hinner hanteras på en viss tid.
Kalenderbitaren
• 1991: den första effektiva implementationen
• 1993: distribuerad Erlang
• 1995: Ericsson gör produktutveckling i Erlang
• 1997: ett tidigt examensarbete om Erlang och SMP
• 1998: Erlang blir öppen källkod
• 2005: den första stabila SMP-versionen
• 2007: stabil version med tillräckligt bra prestandavinster för att vara intressant i produktutveckling.


Det är inte absoluta prestandavärden som är intressanta utan enbart jämförelsen mellan antalet schemaläggare som Erlangs virtuella maskin körs med. Antalet schemaläggare visar hur många trådar som används internt, vilket i praktiken är ett mått på hur många processorkärnor man kan använda samtidigt.

På testmaskinen finns alltså i praktiken åtta kärnor tillgängliga och i diagrammet syns tydligt att prestanda skalar bra upp till just åtta schemaläggare för att sedan sjunka.

Vid en annan mätning på en riktig redan existerande applikation som provkörts i den nya virtuella maskinen med multikärnestöd, har man kunnat konstatera en ökning av prestanda med en faktor 1,65 på en tvåkärnig AMD Opteron jämfört med motsvarande enkärniga processor.
Läs mer

Observera att applikationen är helt oförändrad jämfört med tidigare det vill säga inte byggd från början för att köras i multikärnemiljö.

Applikationen behöver inte ens kompileras om.