Référence entre C, C ++, C #, Python et Go

Benchmark.png

Partager

10 juillet 2011, 22:36 – Mise à jour 11 juillet 2011, 10:24

« 64b2055094″>

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
« E868CD178F »>
« b80a4334dd »>
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 ( &#8220;math&#8221; &#8220;os&#8221; &#8220;flag&#8221; &#8220;log&#8221; &#8220;runtime/pprof&#8221;<br />)<br />var cpuprofile = flag.String(&#8220;cpuprofile&#8221;, &#8220;&#8221;, &#8220;write cpu profile to file&#8221;)<br />func main() { flag.Parse() if cpuprofile != &#8220;&#8221; { 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 &#39;help&#39;.(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 &#39;help&#39;.(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.

« E868CD178F »>
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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *