Programmeringssprog - Ruby vs Go: Fra 30 til 2 servere

Dette forum bruges på EGET ANSVAR til at lege med scripts og andre ting med risiko for at beskadige sit eget og andres systemer.
lath
Indlæg: 5095
Tilmeldt: 27. apr 2008, 02:16
IRC nickname: lars_t_h
Geografisk sted: Fyn

Programmeringssprog - Ruby vs Go: Fra 30 til 2 servere

Indlægaf lath » 29. aug 2013, 15:27

Det her er ret imponerende.

Der er nogle firmaer der har fået nogle gevaldige performance forbedringer ved at bruge Go (ikke Go!) programmeringssproget: http://golang.org

De gik fra at bruge 30 servere med Ruby på der havde en tendens til kollosalt clusterf**k til 2 servere der kører uden problemer (og den ene af de 2 servere er der endda kun på grund af redundanskrav).

http://blog.iron.io/2013/03/how-we-went-from-30-servers-to-2-go.html
http://blog.iron.io/2013/08/go-after-2-years-in-production.html

For det program som iron.io kører, så bruger Go betydeligt mindre RAM (ca 500 KB vs 50 MB) ved opstart, og under drift bruger den kun 5% CPU saft - i forhold til at det før var 50% CPU saft.

Der er mange der bruger Go - blandt de første på den her liste finder du Canonical, der bruger Go på deres servere
http://go-lang.cat-v.org/organizations-using-go

Go er et sprog der oversætter til maskinkode meget hurtigt. Go compileren leverer programmet som en alt-i-en-fil program, så der er absolut ingen afhængigheder.

Go er rigtig god til at køre noget i parallel a la Erlang programmeringssproget.
Det kan multiplekse 10.000er af go rutiner (svarer til Java green threads fra dengang Java 1.4 var helt nyt) ned til nogle få kernel threads.

Pt har jeg droppet Python og bruger nu Go, fordi det er sjovere at kode i Go.

---

Jeg har en ide om at prøve at lave en webapplikation i Go.

Jeg har en ide der på masknen hvor administrationen skal foregå startes en webapplikation (manuelt eller per automatik).
Med en browser, samt et server certifikat+et klient certifikat (evt begge hjemmelavet) kobler administrator sig så op - man bestemmer naturligvis selv)
Webapplikationen startes op på en Linux server/desktop, og kan så på en helt anden desktop (eller samme desktop, hvis den kører webapplikationen), eller en tablet, så få en grafisk brugergrænseflade til at administrere for eksempel pakker på Linux serveren/desktop maskinen.

Det er en slags web udgave af softwarecenteret om man vil. Ideen er at en administrator kan logge ind og nemt installere og fjerne pakker, f.eks. mens han har en bruger i telefon røret.

---

Er du selv blevet interesseret kan du tage Tour'en på http://golang.org - den er på 84 trin, så vidt jeg lige husker, og man kommer rundt om det meste.

/Lars
Jeg er Software ingeniør (Diplomingeniør) i Informationsteknologi og indlejede systemer, hvor indlejrede systemer er computer (microcontroller) + elektronik i for eksempel et TV, en router, en vaskemaskine og den slags

lath
Indlæg: 5095
Tilmeldt: 27. apr 2008, 02:16
IRC nickname: lars_t_h
Geografisk sted: Fyn

Kvadratrodsberegning med Newtons metode

Indlægaf lath » 31. aug 2013, 00:29

Her er en stump Go kode der er implementering af en beregning af kvadratrod ved at bruge Newtons metode:

Kildekode

Kode: Vælg alt

package main

import (
    "fmt"
    "math"
)

func Sqrt(x float64) (z float64) {
    var nævner, tæller float64
    z = x
    for i := 1;i <= 10; i++ {
       nævner = (z * z) - x
       tæller = 2 * z
       z = z - (nævner / tæller)
        fmt.Println("i=",i,",z=", z)
    }
   
    return
}

func main() {
    var a = 2.
    fmt.Println(Sqrt(a))
    fmt.Println(math.Sqrt(a))
}

Lad os antage at du gemmer koden i filen sqrt_newton.go

Før du går igang så skal du sætte en bunke miljø variabler:

Kode: Vælg alt

export GOBASEDIR=$HOME/bin/go
export GOROOT=$GOBASEDIR
export GOPATH=$GOBASEDIR/bin
PATH=$PATH:$GOBASEDIR/bin

Bemærk at kommandoerne antager at din Go mappe er ~/bin/go mappe.
Bruger du en anden mappe så omskriv 1. linie:
  • start med at skrive export GOBASEDIR=
  • uden mellemrumstegn eller noget andet, så tilføj den absolutte sti til mappen
  • Den absolutte sti til mappen må ikke indeholde mellemrumstegn.
  • Du må ikke afslutte med et /-tegn.
De virker uanset hvad dit brugernavn er.
ADVARSEL: Bemærk at du ikke må lave ged i linien med PATH, ellers kan Ubuntu ikke finde dine programmer.

Du kan så vælge at pretty printe (få kildekoden til at se pæn ud, når du læser) den med den her kommando fra samme mappe som filen er i:

Kode: Vælg alt

go fmt sqrt_newton.go


Nu kan du med Go compileren installeret oversættes kildekoden - og det er stadig imens Bash fortolkeren (terminalen) er placeret i samme mappe som kildekoden filen (sqrt_newton.go) er i

Kode: Vælg alt

go build sqrt_newton.go

Ud kommer en ny fil der er et kørbart program med uoptimeret maskinkode, hvilket er årsag til at den fylder 1,5 MB.
Kommandoen

Kode: Vælg alt

ls -lh
giver:
totalt 1,5M
-r-xr-xr-x 1 lars lars 1,5M aug 26 04:10 sqrt_newton
-r--r--r-- 1 lars lars 384 aug 26 04:03 sqrt_newton.go


Du kan nu køre filen med

Kode: Vælg alt

./sqrt_newton

Den skriver:
i= 1 ,z= 1.5
i= 2 ,z= 1.4166666666666667
i= 3 ,z= 1.4142156862745099
i= 4 ,z= 1.4142135623746899
i= 5 ,z= 1.4142135623730951
i= 6 ,z= 1.414213562373095
i= 7 ,z= 1.4142135623730951
i= 8 ,z= 1.414213562373095
i= 9 ,z= 1.4142135623730951
i= 10 ,z= 1.414213562373095
1.414213562373095
1.4142135623730951


Som du kan se så beregner den faktisk kvadratroden af 2.
Det er Sqrt(a) i func Main, der kalder vores funktion func Sqrt, i func Main kan du også se at det første jeg gør er at oprette en variabel a, der tildeles værdien 2:

Kode: Vælg alt

var a = 2.

(et '.'(=punktum) får 2 til at blive til et decimaltal i stedet for et heltal)

Allerede ved det 5 gennemløb har den fat i det helt rigtige tal.
Havde jeg lavet algoritmen lidt smartere, så holder den op med at gentage beregningen i for løkken, når forrige z værdi er meget lidt forskellig fra den nye beregning af z.

Til sammenligning er det sidste programmet gør (det sidste den udskriver) er at bruge math.Sqrt, dvs bruge den indbyggede kvadratrodsalgoritme fra standardbiblioteket.
---

Programmet har ingen afhængigheder.
Afhængigheder kan man se med ldd komandoen.

Kode: Vælg alt

ldd sqrt_newton
som skriver:
ikke et dynamisk kørbart programr

file komandoen viser det også, bare på en anden måde.

Kode: Vælg alt

file sqrt_newton
som giver
sqrt_newton: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Her er det staticallly linked der fortæller dig at der ikke er nogen afhængigheder.


Håber det er sjovt for nogen at læse lidt om hvordan man laver kildekode og så oversætter det.

/Lars
Jeg er Software ingeniør (Diplomingeniør) i Informationsteknologi og indlejede systemer, hvor indlejrede systemer er computer (microcontroller) + elektronik i for eksempel et TV, en router, en vaskemaskine og den slags

lath
Indlæg: 5095
Tilmeldt: 27. apr 2008, 02:16
IRC nickname: lars_t_h
Geografisk sted: Fyn

Re: Programmeringssprog - Ruby vs Go: Fra 30 til 2 servere

Indlægaf lath » 15. sep 2013, 04:01

Jeg fandt lige ud af at der findes noget der både er en online pastebin for Go kildekode og også en online Go compiler (som dog er begrænset så den ikke kan misbruges):
Den findes på http://play.golang.org

Et konkret eksempel er naturligvis kildekoden i mit indlæg ovenover det her indlæg
Gå ind på den her web side: http://play.golang.org/p/lPmVFlOV9h - og tryk på Run knappen på web siden, så vil Go kilekoden blive oversat og kørt af en Go compiler.

Resultatet vises under kildekoden.

/Lars
Jeg er Software ingeniør (Diplomingeniør) i Informationsteknologi og indlejede systemer, hvor indlejrede systemer er computer (microcontroller) + elektronik i for eksempel et TV, en router, en vaskemaskine og den slags

lath
Indlæg: 5095
Tilmeldt: 27. apr 2008, 02:16
IRC nickname: lars_t_h
Geografisk sted: Fyn

Re: Programmeringssprog - Ruby vs Go: Fra 30 til 2 servere

Indlægaf lath » 15. sep 2013, 07:34

Her er iøvrigt den forbedrede udgave der stopper når forskellen er lille nok, eller for-løkken blev kørt for mange(=i_max) gange.
http://play.golang.org/p/E-8mnu3Med
Igen - tryk på Run knappen

Prøv at smide en masse ekstra nuller ind imellem . og 1 i linien:

Kode: Vælg alt

const diff float64 = 0.000000001

tryk på Run og se hvad der sker. Hvis compileren brokker sig, så forsøg dig med færre nuller indtil den ikke længere brokker sig.
Hvis den ikke kører 50 gange så tilføj flere nuller.

Laver du forsøgene herunder, så skal du have masser af ekstra nuller i diff variablen

Hvis den kører 50 gange så prøv at ændre

Kode: Vælg alt

const i_max int32 = 50

... så tallet bliver et større positivt heltal og kør med Run. Prøv også med et mindre positivt heltal.
Hvad sker der, hvis du gør tallet negativt?
Altså: Lav i_max til at blive -50.

Kun 1 gennemløb igennem løkken, hvis i_max er et negativt tal?
Det er fordi at vores test:

Kode: Vælg alt

i >= i_max

i linien

Kode: Vælg alt

if i >= i_max {

... aldeles omgående giver et falsk udsagn, som er det der stopper løkken.

Stadig imens du har mange ekstra nuller i diff og i_max og et negativt tal, så prøv at foretage de her ændringer:
Ændre denne linie fra det her:
func sqrtExitLoopI(i int32, do_loop *bool) {

til det her:

Kode: Vælg alt

func sqrtExitLoopI(i uint32, do_loop *bool) {


og
ændre på i_max variablen. Det er linien som begynder med
const i_max int32 =

Skal du ændre den så den begynder med:

Kode: Vælg alt

const i_max uint32 =

Bemærk at der efter '=' tegnet i vores program skal stå et tal.
Hvis du slettede tallet, så bliver compileren sur, og nægter at lave et program til dig. (prøv det).

Nu er sqrtExitLoopI funktionen fikset, så compileren er glad, men vi skal lige rette i Sqrt funktionen:
Ændr
var i int32 = 1

så der står

Kode: Vælg alt

var i uint32 = 1


Nu er compileren glad, hvad angår 'i' variablerne i Sqrt, og sqrtExitLoopI funktionerne og også i_max variablen, men compileren er ikke helt glad lige nu, fordi du bruger et negativt tal ved i_max variablen.
Du får den her besked:
prog.go:24: constant -50 overflows uint32
[process exited with non-zero status]


Program exited.

Det kan oversættes til at der i en i en uint32 type ikke kan være et negativt tal, for det er hvad u'et i uint betyder.
U'et er fra ordet unsigned, der betyder at den mest betydende bit(MSb) ikke er reserveret til at angive om at tallet er negativt (logisk 1), eller enten positivt eller nul (logisk 0).

Prøv at ændre i_max til et passende stort positivt heltal, f.eks. 100.000 og kør igen med Run.
Du får den her besked:
Error communicating with remote server.
Program exited.

... og det er en af begræningerne på play.golang.org du er løbet ind, nemlig at Go programmerne kun kan køre i meget kort tid. - Ingen gratis Google App Engine hosting her.

Installerer du derimod Go compileren og har kildekoden i proc.go, så vil den her 3-i-1 kommando både oversætte kildekoden til maskinkode, lave dig et Linux program (linke det) og køre programmet:

Kode: Vælg alt

rm -f ./proc.go;go build proc.go;./proc

Kommandoen virker kun, hvis terminalen er i samme mappe som 'proc.go'.
Får du compiler fejl bliver programmet './proc' ikke lavet og du får en 'fil ikke fundet' fejl fra terminalen.
Du kan kan afbryde et terminalprogram med tastekombination CTRL+C - det er den der normalt er kopier til udklipsholderen i GUI programmer og desktoppen. I terminalen har den bare en anden betydning.

/Lars
Jeg er Software ingeniør (Diplomingeniør) i Informationsteknologi og indlejede systemer, hvor indlejrede systemer er computer (microcontroller) + elektronik i for eksempel et TV, en router, en vaskemaskine og den slags

Tilbage til "Sandkassen"

Hvem er online

Brugere der læser dette forum: [Bot] og 0 gæster