Benchmark entre C, C ++, C #, Python e Go

benchmark.png

Compartilhar

julho 10, 2011, 22:36 – Atualizado 11 de julho de 2011, 10:24

Após escrever a entrada anterior sobre a linguagem de programação Go e ler um Comente onde é dito que ir é bastante lento, eu decidi fazer benchmarks muito simples.

A ideia é comparar a velocidade de execução do reembolso do logaritmo natural de um determinado número e a introdução dele em um mapa ou hash. Obviamente, a velocidade depende em grande medida na implementação do recipiente em cada idioma.

Quanto a ir, usei o compilador 6G com base no Inferno porque eu não quero instalar uma versão instável do Compilador GCC em Me Gentoo Linux e cagando grande, adicionando o GCGO otimiza o código mais de 6g.

Nota: Este benchmark é bastante surrado e simploso, eu apenas fiz para aliviar minha curiosidade e ver mais ou menos por onde o desempenho de Go foi. No futuro e quando tenho mais tempo, farei um sério adicionando Java, Ruby e Scala.

Implementação C

Vamos começar com o implemento em C de este benchmark simples. Eu usei as bibliotecas Uthah para criar o hash, você pode encontrá-los em sourceforge

código bechmark.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;}

compilação

genbeta@dev $ gcc -O3 -Wall -c -fmessage-length=0 -MMD -MP -std=c99 benchmark.cgcc -lm -o cbench benchmark.o

Implementação C ++

para C ++ Utilizamos o contêiner do mapa do código 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;}

compilação

genbeta@dev $ g++ -O3 -Wall -c -fmessage-length=0 -MMD -MP benchmark.cpp -o cppbenchmark.og++ -o cppbench cppbenchmark.o

implementação em mono c #

Especialistas em .NET C # Deixe-me perdoar-me, mas não tenho idéia de c # Eu não sei se esse trecho é muito bom, mas o caso é que ele funciona muito bem, se houver algum erro que imploro para corrigir eu.

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)); } } }}

compilação

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"

Implementação em Python

Esta é certamente mais simples de todos 🙂

código de referência

import mathd = {}for i in range(1, 5000000): d = math.log(i)

implementação em Ir

Isso também é muito simples, é mais ou menos em par com C ++

benchmark.go código

package mainimport "math"func main() { m := make(map float64) var i float64 = 1 for ; i < 5000000.; i++ { m = math.Log(i) }}

compilação

genbeta@dev $ 6g benchmark.go && 6l benchmark.6 && mv 6.out gobench

benchmarking

para a execução dos benchmarks i Use o comando de tempo do GNU no seguinte sistema:

  • sistema operacional: gentoo linux
  • arquitetura: x86_64
  • processador: cpu Intel® Core ™ i7 @ 2.80GHz
  • RAM Velocidade: 1666
TH> Idioma

Sistema de tempo tempo tempo real Usando a CPU RAM usando alterações de contexto
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,70 99% 2442032kb 280
go 2.76S 0.16s 2.93s 99% 1044304kb 1

é digno de nota como c # é o mais rápido com 2.01, eu não tenho ideia se isso é assim para A implementação do macaco, da própria língua, ou se eu não tiver feito bem o benchmark em C #, mas a verdade é que estou agradavelmente impressionado. Ainda é perto de C com 2.19s, então a implementação pypton 2.7 com 2,70, depois que ele tem uma vez para ir com 2,93, a implementação de CPYthon 2.7 continua com 3,86 e muito tristemente o último lugar C ++ está ocupado com A 4,24

Também podemos apreciar como um macaco e o pipule usar mais de um núcleo do meu processador i7, enquanto o resto só usa um núcleo em 99%.

em relação ao consumo de memória, c ++ é o mais ideal próximo por completo. C # e Python – Em ambas as implementações – faça um uso muito maior de recursos.

Go,

mas olho, esse benchmark foi executado sem usar o perfil em movimento. Em movimento, ferramentas de criação de perfil são usadas para detectar gargalos e corrigi-los melhorando consideravelmente. O papel a quem um usuário referido no post anterior é um benchmark sem perfil em ir e já teve sua resposta dos criadores da linguagem no blog oficial.Vamos usar perfil para ver o quanto podemos melhorar o desempenho de nosso snippet em vão.

primeiro, modificamos o código de nossa função para adicionar suporte para cpupproping, nosso código seria assim:

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) }

}

agora podemos executar o snippet com o Parâmetro CPUProfile e depuração com 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)

Podemos ver que o aplicativo ocupa a maioria dos ciclos da CPU e o tempo de execução em valores inseridos no mapa. A aplicação refinada desenvolvida em curso com Gopprof vai muito além da intenção desta entrada, mas verificando as listagens do código e as amostras usadas em cada linha que podemos saber que o gargalo está na linha que acumula 285 das 290 amostras da execução.

Está claro que o uso de um mapa para este benchmark não é ideal e poderíamos usar uma fatia para armazenar os dados. Se editarmos o arquivo e comentamos na linha /*m := make(map float64)*/ e usar uma fatia em vez de um mapa var p float64; m := make(float64, len(p)) e gerar um arquivo .prof e nós Reald:

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)

Verifique que agora a prática do tempo é dedicada à função que retorna o logaritmo natural do i e não há mais gargalo. Vamos apagar o código que introduz a funcionalidade de reforma, comentando e passamos o benchmark novamente.

tempo de usuário tempo tempo real Usando a CPU usando a RAM alterações de contexto
ir 0.22s 0.01s 0,24S 99% 314512kb 1

Ai! Uma melhoria notável. Mas vamos ser justo, vamos mudar o hash na implementação de C por uma matriz simples e converter o benchmark para calcular o logaritmo natural do IE Inserir o valor em uma matriz.

tempo do usuário sistema de tempo tempo real Uso de CPU Uso de RAM Alterações de contexto
c 0.31s 0.00 0,31 S 99% 1824kb 1
go 0,22 s 0.01s 0,24S 99% 314512kb 1

Neste caso, vá é ainda mais rápido que c devolver o logaritmo natural de i.

conclusão

Parece que o tipo map não é muito fino em vão, ainda assim, a velocidade . A ficção linguística é entre C e C ++. Nesse caso, não podemos fazer nada cem legítimos para eliminar o gargalo porque é uma parte específica do teste que fizemos. Eu não sei se você tem que esperar quatro anos como eu li aí que a linguagem é mais madura ou não. É claro que a maturidade ainda não tem e precisa de algumas implementações em sistemas para melhorar. E se eu souber é que eu sou pelo menos eu vou seguir a faixa, e mais agora que está disponível no Google App Engine e é mais eficiente do que Python e Java.

Mais sobre Genbeta dev | Introdução à linguagem de programação Go

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *