Partager
Après avoir écrit l’entrée précédente sur la langue de programmation et la lecture d’un commentaire où il est dit que Go est assez lent, j’ai décidé de faire des points de repère très simples.
L’idée est de comparer la vitesse d’exécution du remboursement du logarithme naturel d’un nombre donné et de l’introduction de celui-ci dans une carte ou un hachage. Évidemment, la vitesse dépend dans une large mesure de la mise en œuvre du conteneur dans chaque langue.
comme pour aller, j’ai utilisé le compilateur 6G basé sur Inferno car je ne veux pas installer une version instable de la Compilateur de GCC en moi Gentoo Linux et le chier grand, ajout de GCGO optimise le code plus de 6g.
Remarque: cette référence est assez shabby et simplifie, je viens de le faire pour soulager ma curiosité et voir plus ou moins par où allez la performance de Go. À l’avenir et quand j’ai plus de temps, je ferai un sérieux en ajoutant Java, Ruby et Scala.
Mise en œuvre C
Nous allons commencer par l’implémentation en C de ce simple référence. J’ai utilisé les bibliothèques uthah pour créer le hachage, vous pouvez les trouver dans SourceForge
Code Becnhmark.c
#include <math .h>#include "uthash.h"struct map { float id; float value; UT_hash_handle hh;};struct map *dict = NULL;void add_data(float data_id, float data){ struct map *m; m = malloc(sizeof(struct map)); m->id = data_id; m->value = data; HASH_ADD_INT( dict, id, m );}int main(){ for (int i = 0; i < 5000000; i++) { add_data(i, log(i)); } return 0;}
Compilation
genbeta@dev $ gcc -O3 -Wall -c -fmessage-length=0 -MMD -MP -std=c99 benchmark.cgcc -lm -o cbench benchmark.o
Mise en œuvre C ++
pour C ++ Nous utilisons le conteneur de carte du code STL
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
mise en œuvre dans mono c #
Experts en .net C # Laissez-moi me pardonner mais je n’ai aucune idée de c # Je ne sais pas si cet extrait est très bon, mais le cas est que cela fonctionne bien, s’il y a une erreur, je vous prie de corriger Moi.
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"
Mise en œuvre dans Python
C’est sûrement le plus simple de tous 🙂
Code de référence
import mathd = {}for i in range(1, 5000000): d = math.log(i)
Mise en œuvre Go
Ceci est également très simple, il est plus ou moins à égalité avec C ++
Benchmark.go Code
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
pour l’exécution des repères I Utilisez la commande GNU Time sur le système suivant:
- Système d’exploitation: Gentoo Linux
- Architecture: x86_64
- Processeur: Intel® Core ™ I7 CPU @ 2.80GHz
- Vitesse de RAM: 1666
Langue | TEMPS UTILISATE | SYSTÈME TIME | TIME REAL | Utilisation de la CPU | RAM en utilisant | Contexte change |
---|---|---|---|---|---|---|
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 pyy-c1.5 | 1,57S | 0,33s | 2.70s | 99% | 2442032kb | 280 |
go | 2.76s | 0,16S | 2.93S | 99% | 1044304KB | 1 |
est remarquable que c # est le plus rapide de 2,01, je n’ai aucune idée si c’est comme ça pour La mise en œuvre du singe, la langue elle-même, ou si je n’ai pas bien fait la référence en C # mais la vérité est que je suis agréablement impressionné. Il est toujours proche de C avec 2,19 ans, puis la mise en œuvre du Pypy de Python 2.7 avec 2,70, après avoir un tour de 2,93, la mise en œuvre de CPPHON 2.7 continue avec 3,86 et très tristement la dernière place C ++ est occupée avec A 4.24
Nous pouvons également apprécier en tant que singe et pypy utiliser plus d’un noyau de mon processeur I7, tandis que le reste utilise uniquement un noyau à 99%.
Consommation de la mémoire, c ++ est le plus optimal de près. C # et Python – dans les deux implémentations – apportez une utilisation beaucoup plus grande des ressources.
Go Profiling
mais Eye, que la référence a été exécutée sans utiliser le profilage. En allez, des outils de profilage sont utilisés pour détecter des goulots d’étranglement et leur réparer considérablement. Le papier à qui un utilisateur mentionné dans le poste précédent est une référence sans profilage d’aller et a déjà eu sa réponse des créateurs de la langue sur le blog officiel.Nous allons utiliser le profilage pour voir combien nous pouvons améliorer la performance de notre extrait de votre extrait.
Tout d’abord, nous modifions le code de notre fonction pour ajouter de la prise en charge de CPUPProphing, notre code serait comme ceci:
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) }
}
Nous pouvons maintenant exécuter l’extrait avec le Paramètre CPUProfile et débogez-le avec 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)
Nous pouvons voir que l’application occupe la plupart des cycles de la CPU et le temps d’exécution dans la saisie de valeurs sur la carte. La demande raffinée développée avec GOPPROF va bien au-delà de l’intention de cette entrée, mais la vérification des listes du code et des échantillons utilisés dans chaque ligne, nous pouvons savoir que le goulot d’étranglement est sur la ligne qui accumule 285 des 290 échantillons de l’exécution.
Il est clair que l’utilisation d’une carte pour ce benchmark n’est rien d’optimal et nous pourrions utiliser une tranche pour stocker les données. Si nous édions le fichier et que nous avons commenté sur la ligne /*m := make(map float64)*/
et utilisez une tranche au lieu d’une carte var p float64; m := make(float64, len(p))
et générer un fichier .prof. grondal:
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)
Nous vérifions maintenant que la pratique du temps est dédiée à la fonction qui renvoie le logarithme naturel de i
et il n’y a plus de goulot d’étranglement. Nous supprimerons le code qui introduit la fonctionnalité de rénovation en commentant et nous transmettons à nouveau la référence.
Langue | TEMPS UTILISATEUR | SYSTÈME TIME | TIME REAL | Utilisation de la CPU Utilisation de RAM | Contexte change | |
---|---|---|---|---|---|---|
go | 0,22s | 0,01s | 0,24s | 99% | 314512kb | 1 |
AL! Une amélioration remarquable. Mais soyons juste, nous allons changer le hash dans la mise en œuvre de C par un tableau simple et convertirons la référence en calculant simplement le logarithme naturel de IE Entrez la valeur dans un tableau.
Langue | TIME UTILISATEUR | SYSTEME TIME | utilisation CPU | utilisation de RAM | Contexte change | |
---|---|---|---|---|---|---|
c | 0,31s | 0.00S | 0.31 S | 99% | 1824kb | 1 |
go | 0,22 s | 0,01s | 0,24s | 99% | 314512kb | 1 |
Dans ce cas, c’est même plus vite que c retourner le logarithme naturel de .
Conclusion
Il semble que le type map
n’est pas très mince, toujours, la vitesse ye . La fiction linguistique est entre C et C ++. Dans ce cas, nous ne pouvons rien faire cent légitime pour éliminer le goulot d’étranglement car c’est une partie spécifique du test que nous avons fait. Je ne sais pas si vous devez attendre quatre ans, car j’ai lu là que la langue est plus mature ou non. Il est clair que la maturité manque toujours et nécessite quelques implémentations dans les systèmes pour pouvoir s’améliorer. Et si je sais, c’est que je suis au moins je vais suivre la piste, et plus maintenant qu’il est disponible sur Google App Moteur et est plus efficace que Python et Java.
Plus sur Genbeta dev | Introduction au langage de programmation Go