Condividi
Dopo aver scritto la voce precedente sul linguaggio di programmazione Vai e la lettura di un linguaggio di programmazione Go Commenta dove si dice che vada è piuttosto lento, ho deciso di fare benchmark molto semplici.
L’idea è di confrontare la velocità di esecuzione del rimborso del logaritmo naturale di un dato numero e dell’introduzione di esso in una mappa o hash. Ovviamente, la velocità dipende in larga misura sull’attuazione del contenitore in ciascuna lingua.
Come per andare, ho utilizzato il compilatore 6G basato su Inferno perché non voglio installare una versione instabile del Compilatore GCC in Me Gentoo Linux e cattivandolo grande, aggiungendo il GCGO ottimizza il codice più di 6G.
Nota: questo benchmark è piuttosto squallido e Simplose, l’ho fatto per alleviare la mia curiosità e vedere più o meno da dove era la performance di Go. In futuro e quando ho più tempo, lo farò seriamente aggiungendo Java, Ruby e Scala.
Implementazione C
Cominciamo con l’attrezzo in c di Questo semplice benchmark. Ho usato le librerie di Uthash per creare l’hash, puoi trovarle in Sourceforge
codice becnhmark.c
compilation
genbeta@dev $ gcc -O3 -Wall -c -fmessage-length=0 -MMD -MP -std=c99 benchmark.cgcc -lm -o cbench benchmark.o
Implementazione C ++
per c ++ Utilizziamo il contenitore della mappa del codice Ben
Benchmark.cpp
#include <iostream>#include <map>#include <cmath>using namespace std;int main(){ map <float , float> dict; for (int i = 0; i < 5000000; i++) { dict = log(i); } return 0;}
compilation
genbeta@dev $ g++ -O3 -Wall -c -fmessage-length=0 -MMD -MP benchmark.cpp -o cppbenchmark.og++ -o cppbench cppbenchmark.o
Implementazione in mono c #
Esperti in .NET C # Lasciami perdonami ma non ho idea di c # Non so se questo snippet è molto buono, ma il caso è che funzioni fantastico, se c’è qualche errore ti prego di correggere me.
benchmark.cs
using System;using System.Collections;namespace CSBenchmark{ class MainClass { public static void Main (string args) { Hashtable dict = new Hashtable(); for (int i = 0; i < 5000000; i++) { dict.Add(i, Math.Log(i)); } } }}
compilation
genbeta@dev $ /usr/bin/gmcs /noconfig "/out:./benchmark.exe" "/r:/usr/lib/mono/2.0/System.dll" /nologo /warn:4 /debug:+ /debug:full /optimize- /codepage:utf8 /platform:x86 "/define:DEBUG" /t:exe "./benchmark.cs"
Attuazione in Python
Questo è sicuramente il più semplice di tutti 🙂
codice di benchmark
import mathd = {}for i in range(1, 5000000): d = math.log(i)
Implementazione in Vai
Anche questo è molto semplice, è più o meno alla pari con C ++
benchmark.go codice
package mainimport "math"func main() { m := make(map float64) var i float64 = 1 for ; i < 5000000.; i++ { m = math.Log(i) }}
compilation
genbeta@dev $ 6g benchmark.go && 6l benchmark.6 && mv 6.out gobench
benchmarking
per l’esecuzione dei benchmark i Utilizzare il comando del tempo GNU sul seguente sistema:
- Sistema operativo: Gentoo Linux
- Architettura: x86_64
- Processore: Intel® Core ™ I7 CPU @ 2.80GHz
- velocità ram: 1666
LINGUA | Tempo utente | Sistema di tempo | Tempo reale | Utilizzo della CPU | RAM usando | Cambia contesto |
---|---|---|---|---|---|---|
C | 1.90s | 0,27S | 2.19s | 99% | 1826704kb | 1 |
C ++ | 4.07S | 0.14s | 4.24S | 99 % | 941808kb | 1 |
c # | 1.72s | 0,29 S | 2.01s | 131% | 2032176kb | 1155 |
python Cpy. Thon 2.7.2 | 3.43s | 0.37s | 3.86s | 99% | 2101312kb | 1 |
PYTHON PYPY-C1.5 | 1.57S | 0.33S | 2.70s | 99% | 2442032kb | 280 |
go | 2.76S | 0,16S | 2.93S | 99% | 1044304KB | 1 |
è degno di nota come C # è il più veloce con 2,01, non ho idea se è così per L’implementazione della scimmia, della lingua stessa, o se non ho fatto bene il benchmark in c # ma la verità è che sono piacevolmente colpito. È ancora vicino a C con 2.19s, quindi l’implementazione del python 2.7 di Python 2.7 con 2.70, dopo che ha un turno di andare con 2.93, l’implementazione di CPYTHON 2.7 continua con 3.86 e molto tristemente l’ultimo posto C ++ è occupato con A 4.24
Possiamo anche apprezzare come una scimmia e un pyyy utilizzare più di un nucleo del mio processore i7 mentre il resto utilizza solo un nucleo al 99%.
Per quanto riguarda il consumo di memoria, c ++ è il più ottimale strettamente vicino. C # e Python – in entrambe le implementazioni: fare un uso molto maggiore delle risorse.
Go Profiling
Ma occhio, che il benchmark è stato eseguito senza usare la profilazione in movimento. In movimento, gli strumenti di profilazione vengono utilizzati per rilevare i colli di bottiglia e fissarli notevolmente. La carta a cui un utente di cui al post precedente è un punto di riferimento senza profilatura in movimento e ha già avuto la sua risposta dai creatori della lingua nel blog ufficiale.Useremo la profilazione per vedere quanto possiamo migliorare le prestazioni del nostro snippet in movimento.
In primo luogo, modifichiamo il codice della nostra funzione per aggiungere supporto per cpuprophing, il nostro codice sarebbe come questo:
package main<br />import ( “math” “os” “flag” “log” “runtime/pprof”<br />)<br />var cpuprofile = flag.String(“cpuprofile”, “”, “write cpu profile to file”)<br />func main() { flag.Parse() if cpuprofile != “” { f, err := os.Create(cpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } m := make(map float64)
var i float64 = 1 for ; i < 5000000.; i++ { m = math.Log(i) }
}
Ora possiamo eseguire lo snippet con il Parametro CPUProfile e debug IT con GOPPROF:
./gobench -cpuprofile=gobench.profgopprof gobench gobench.profWelcome to pprof! For help, type 'help'.(pprof) top10Total: 290 samples 149 51.4% 51.4% 224 77.2% hash_insert_internal 32 11.0% 62.4% 32 11.0% math.Log 17 5.9% 68.3% 17 5.9% runtime.mcpy 17 5.9% 74.1% 17 5.9% runtime.memmove 16 5.5% 79.7% 16 5.5% memhash 13 4.5% 84.1% 13 4.5% runtime.memclr 13 4.5% 88.6% 13 4.5% scanblock 8 2.8% 91.4% 250 86.2% runtime.mapassign 5 1.7% 93.1% 8 2.8% MHeap_AllocLocked 5 1.7% 94.8% 5 1.7% memwordcopy(pprof)
Possiamo vedere che l’applicazione occupa la maggior parte dei cicli della CPU e il runtime nell’inserimento dei valori Nella mappa. L’applicazione raffinata sviluppata in Vai a GOPPROF va ben oltre l’intenzione di questa voce, ma controllando gli annunci del codice e i campioni utilizzati in ciascuna linea possiamo sapere che il collo di bottiglia è sulla linea Accumula 285 dei 290 campioni dell’esecuzione.
È chiaro che l’uso di una mappa per questo benchmark non è nulla di ottimale e potremmo usare una fetta per memorizzare i dati. Se modifichiamo il file e commentiamo sulla riga /*m := make(map float64)*/
e utilizzare una fetta invece di una mappa var p float64; m := make(float64, len(p))
e generare un file .prof e noi SCORD:
Welcome to pprof! For help, type 'help'.(pprof) top10 -cumTotal: 25 samples 7 28.0% 28.0% 25 100.0% main.main 0 0.0% 28.0% 25 100.0% runtime.initdone 0 0.0% 28.0% 25 100.0% runtime.mainstart 18 72.0% 100.0% 18 72.0% math.Log(pprof)
Controlliamo che ora la pratica del tempo è dedicata alla funzione che restituisce il logaritmo naturale di e non c’è più un collo di bottiglia. Elimineremo il codice che introdurremo la funzionalità di ristrutturazione commentando e passiamo di nuovo il benchmark.
LINGUA | THE TIME | Sistema di tempo | TEME TEMPO | UTILIZZO DELLA CPU | UTILIZZARE RAM | Cambia contesto |
---|---|---|---|---|---|---|
Vai | 0,22S | 0.01S | 0.24S | 99% | 314512kb | 1 |
Ouch! Un notevole miglioramento. Ma siamo giusti, cambieremo l’hash nell’attuazione di C da un semplice array e convertiremo il benchmark in calcolo semplicemente il logaritmo naturale di IE immettere il valore in un array.
LINGUA | Tempo utente | Sistema di tempo | Tempo reale | Utilizzo della CPU | Uso della RAM | Modifiche del contesto |
---|---|---|---|---|---|---|
C | 0.31S | 0.00S | 0.31 S | 99% | 1824kb | 1 |
go | 0,22 s | 0,01s | 0,24s | 99% | 314512kb | 1 |
In questo caso, vai è ancora più veloce di c che ritorna il logaritmo naturale di .
conclusione
Sembra che il tipo map
non sia molto sottile in movimento, ancora, la velocità . La finzione linguistica è tra C e C ++. In questo caso, non possiamo fare nulla cento legittimo per eliminare il collo di bottiglia perché è una parte specifica del test che abbiamo fatto. Non so se devi aspettare quattro anni come ho letto lì che la lingua è più matura o meno. È chiaro che la scadenza non ha ancora bisogno e ha bisogno di alcune implementazioni nei sistemi per essere in grado di migliorare. Cosa succede se lo so è che sono almeno di seguire la pista, e più ora che è disponibile su Google App Engine ed è più efficiente di Python e Java.
More On Genbeta Dev |. Introduzione al linguaggio di programmazione Go