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

43 comentarios

benchmark.png

Después de escribir la anterior entrada sobre el lenguaje de programación go y de leer un comentario donde se dice que Go es bastante lento, me he decidido a realizar unos benchmarks muy sencillos.

La idea es comparar la velocidad de ejecución de la devolución del logaritmo natural de un número dado y la introducción del mismo en un mapa o hash. Obviamente, la velocidad depende en gran medida de la implementación del contenedor en cada lenguaje.

En cuanto a Go, he usado el compilador 6g basado en Inferno por que no quiero instalar una versión inestable del compilador GCC en mi Gentoo Linux y cagarla a lo grande, supuéstamente, el gccgo optimiza más el código que el 6g.

NOTA: Este benchmark es bastante cutre y simplón, solo lo hice para aliviar mi curiosidad y ver más o menos por donde andaba el rendimiento de Go. En el futuro y cuando tenga más tiempo, haré uno en serio añadiendo Java, Ruby y Scala.

Implementación C

Vamos a empezar por la implementación en C de este sencillo benchmark. He utilizado las librerías uthash para crear al Hash, puedes encontrarlas en sourceforge

Código 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;
}

Compilación

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

Implementación C++

Para C++ usamos el contenedor map de la STL

Código 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[i] = log(i);
        }
        return 0;
}

Compilación

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

Implementación en C# de Mono

Los expertos en .NET C# que me perdonen pero no tengo ni idea de C# no se si este snippet está muy bien pero el caso es que funciona de maravilla, si hay algún error ruego que me corrijan.

Código 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));				
			}
		}
	}
}

Compilación

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"

Implementación en Python

Esta sea seguramente la más sencilla de todas :)

Código benchmark.py

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

Implementación en Go

Esta también es muy sencilla, está más o menos a la par con C++

Código benchmark.go

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

Compilación

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

Benchmarking

Para la ejecución de los benchmarks utilizo el comando time de GNU sobre el siguiente sistema:

  • Sistema Operativo: Gentoo Linux
  • Arquitectura: x86_64
  • Procesador: Intel® Core™ i7 CPU @ 2.80GHz
  • Velocidad RAM: 1666

LenguajeTiempo UsuarioTiempo SistemaTiempo RealUso de CPUUso de RamCambios de Contexto
C1.90s0.27s2.19s99%1826704kB1
C++4.07s0.14s4.24s99%941808kB1
C#1.72s0.29s2.01s131%2032176kB1155
Python CPython 2.7.23.43s0.37s3.86s99%2101312kB1
Python PyPy-c1.51.57s0.33s2.70s99%2442032kB280
Go2.76s0.16s2.93s99%1044304kB1

Es destacable como C# es el más rápido con 2.01, no tengo ni idea de si eso es así por la implementación de Mono, del lenguaje en si, o si es que no he hecho bien el benchmark en C# pero lo cierto es que estoy gratamente impresionado. Le sigue muy de cerca C con 2.19s, después la implementación PyPy de Python 2.7 con 2.70, tras él le toca el turno a Go con 2.93, la implementación de CPython 2.7 le sigue con 3.86 y muy tristemente el último lugar lo ocupa C++ con un 4.24

También podemos apreciar como Mono y PyPy utilizan más de un núcleo de mi procesador i7 mientras que el resto solo utilizan un núcleo al 99%.

En cuanto al consumo de memoria, C++ es el más óptimo seguido muy de cerca por Go. C# y Python —en ambas implementaciones— hacen un uso mucho mayor de recursos.

Go Profiling

Pero ojo, ese benchmark ha sido ejecutado sin utilizar profiling en Go. En Go se usan las herramientas de profiling para detectar cuellos de botella y arreglarlos mejorando el rendimiento considerablemente. El paper al que un usuario hacía referencia en el anterior post, es un benchmark sin profiling en Go y ya ha tenido su respuesta por parte de los creadores del lenguaje en el blog oficial. Vamos a utilizar profiling a ver cuanto podemos mejorar el rendimiento de nuestro snippet en Go.

Primero modificamos el código de nuestra función para añadir soporte para cpuprofiling, nuestro código quedaría así:

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] float64)

var i float64 = 1 for ; i < 5000000.; i++ { m[i] = math.Log(i) } }

Ahora podemos ejecutar el snippet con el parámetro cpuprofile y depurarlo con gopprof:

./gobench -cpuprofile=gobench.prof
gopprof gobench gobench.prof
Welcome to pprof!  For help, type &#39;help&#39;.
(pprof) top10
Total: 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 la aplicación ocupa la mayoría de los ciclos de la CPU y el tiempo de ejecución en introducir valores en el map. El depurado de aplicaciones desarrolladas en Go con gopprof va mucho más allá de la intención de esta entrada, pero comprobando los listados del código y los samples empleados en cada línea podemos saber que el cuello de botella esta en la línea m[i] = math.Log(i) que acumula 285 de los 290 samples de la ejecución.

Queda claro que el uso de un map para esta benchmark no es nada óptimo y podríamos utilizar un slice para almacenar los datos. Si editamos el archivo y comentamos la linea /*m := make(map[float64] float64)*/ y usamos un slice en lugar de un map var p [5000000]float64; m := make([]float64, len(p)) y volvemos a generar un archivo .prof y depuramos:

Welcome to pprof!  For help, type &#39;help&#39;.
(pprof) top10 -cum
Total: 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)

Comprobamos que ahora la práctica totalidad del tiempo está dedicada a la función que devuelve el logaritmo natural de i y ya no hay ningún cuello de botella. Vamos a eliminar el código que introduce la funcionalidad de depurado comentándolo y pasemos el benchmark otra vez.

LenguajeTiempo UsuarioTiempo SistemaTiempo RealUso de CPUUso de RamCambios de Contexto
Go0.22s0.01s0.24s99%314512kB1

Ouch! Una mejoría notable. Pero seamos justos, vamos a cambiar el hash en la implementación de C por un simple array y convertir el benchmark en simplemente calcular el logaritmo natural de i e introducir el valor en un array.

LenguajeTiempo UsuarioTiempo SistemaTiempo RealUso de CPUUso de RamCambios de Contexto
C0.31s0.00s0.31s99%1824kB1
Go0.22s0.01s0.24s99%314512kB1

En este caso, Go es incluso más rápido que C devolviendo el logaritmo natural de i.

Conclusión

Parece que el tipo map no está muy fino en Go, aún así, la velocidad y eficiencia del lenguaje está entre C y C++. En este caso, no podemos hacer nada cien por cien legítimo por eliminar el cuello de botella por que es parte específica del test que hemos realizado. No se si hay que esperar cuatro años como he leído por ahí a que el lenguaje esté más maduro o no. Está claro que aún le falta madurez y necesita unas cuantas implementaciones en sistemas para poder mejorar. Lo que si que se es que yo al menos le voy a seguir la pista, y más ahora que está disponible en Google App Engine y es más eficiente que Python y Java.


Más en Genbeta Dev | Introducción al lenguaje de programación Go

Anunciate aquí
Anunciate aquí
Anunciate aquí

¿Quieres saber más?

Productos

Información de Productos relacionados con el artículo

Ver más

Artículos

Artículos relacionados que probablemente también te interesen

Ver más

Respuestas

Preguntas sobre este tema que ha contestado la comunidad

+ Deja tu comentario

Comentarios

  • 1

    Avatar de gentooxativa !

    Bastante interesante, mañana le dare un ojo al Go :P

  • 2

    !
    | 1 estrellas

    En mi humilde opinión, no se pueden dar conclusiones generales acerca del rendimiento basándose solo en la implementación del hash y de la función logaritmo.

    Quizás sería interesante realizar una serie de operaciones sobre una imagen (todos sus píxeles) mediante operadores clásicos de los lenguajes, sin utilizar funciones del sistema. De esta forma quizás se podría ver la diferencia de rendimiento, sin depender de una función en particular.

  • Respondiendo a #2:
  • 5

    Avatar de Oscar Campos !

    Estoy de acuerdo, pero no tengo demasiado tiempo como para acometer un benchmark menos chorra que el que he hecho.

    Si alguien se anima a hacer un benchmark más en condiciones, si me pasa los datos puedo hacer un artículo con esos datos.

    Eso si, debe de incluirse el código de los mismos para poder correrlos en local yo mismo.

    Saludos.

  • 3

    Avatar de alexandernst !

    No es que no aprecie el esfuerzo, pero este benchmark es chistoso, mal hecho, sin base alguna, y lo mas grave, no da una idea real sobre la velocidad que se puede ganar con cada lenguaje. Desde cuando los benchmarks se hacen con una sola prueba usando una sola función matemática?

    ¿Y desde cuando Python gana en algo a C? (estamos hablando de rapidez, no de facilidad a la hora de programar).

  • Respondiendo a #3:
  • 6

    Avatar de Oscar Campos !

    No veo donde ha dado Python mejor rendimiento que C, ¿tú lo ves?.

    En cuanto al benchmark, pues si, es bastante chorra. Por no usar solo una función matemática he utilizado tb un hash o map con indexación no se si te habías fijado...

    Además si lees las conclusiones digo claramente que la eficacia está entre C y C++ no le doy valor alguno al último benchmark con solo la función "log".

    Pero te remito al comentario de arriba, si tienes tiempo y ganas de hacer un benchmark mejor y mandarme código y resultados estaré encantado de escribir un artículo sobre ello para que todo el mundo pueda hacerse una idea "real sobre la velocidad que se puede ganar con cada lenguaje".

    Saludos.

  • Respondiendo a #3:
  • 9

    !
    | 1 estrellas

    Menos mal que aprecias su esfuerzo xDD

  • Respondiendo a #6:
  • 10

    Avatar de alexandernst !

    Phoronix

  • Respondiendo a #10:
  • 21

    !

    Si lo viste en Phoronix entonces responde en Phoronix! claramente no es un Benchmark de lo más técnico, pero al menos está bien logrado para hacerse una idea bastante general

  • 4

    Avatar de gabrielon !

    Así, a simple vista. ¿ Los valores de RAM son correctos ? ¿ KB ? Más ideas .. programo C# casi a diario y destaco que pueden haber diferencias en tiempo entre una primera y segunda ejecución (temas de carga de librerías, y quizás el motivo de uso de varios procesadores. No hay ningun threading adicional para que se permita un uso de varios procesadores). Supongo que también sucecerá con los demas lenguajes. ¿ Como has medido los tiempos ? Creo que deberías hacer correr los programas despues de un reboot, y posteriormente haciendo la media de tiempo de varias ejecuciones. Por todos es sabido que en tiempos C < C++ < C# < Python.

    Por cierto, las '{' yo las escribo en C# como tu lo has hecho en C. :)

    ¿ Por que utilizas float de 64 bits en Go para calcular el logaritmos y en el resto enteros ? ¿ No hay una converisoón de tipos en el resto de lenguajes que puede propiciar un decremento de rendimiento ? En C# podrías poner un 'for(double i; i < 5000000.0m; i++)' a ver lo que pasa.

    Saludos

  • Respondiendo a #4:
  • 11

    Avatar de Oscar Campos !

    He medido todos los tiempos con la función time de GNU (no la que viene con bash) que también me daba los datos de la memoria (que supongo que serían datos de virtual + real).

    En cuanto los tipos de las variables, si te fijas, todos los resultados de log son de tipo double, en Go lo de usar un float64 para i es por que la función Log del paquete math solo admite un parámetro de tipo float64.

    Saludos.

  • Respondiendo a #11:
  • 13

    Avatar de gabrielon !

    Entonces es que Go no tiene conversion de tipos automático.

    http://msdn.microsoft.com/en-us/library/x80ywz41.aspx

    La funcion log solo "admite" doubles también. Aunque internamente se hace la conversíon y eso cuesta ciclos.

  • 7

    !
    | 1 estrellas

    Y java ????

    import java.util.Hashtable;

    public class HastTest {

    public static void main(String[] args) {

    Hashtable table = new Hashtable(); for(int i = 0 ; i < 5000000 ; i++){ table.put(i,Math.log(i)); }

    }

    }

    Mac Intel Core 2 Duo 2.4 4g ddr2 ram 800mhz x86_64

    time java -Xms512m -Xmx1024m HastTest

    real 0m4.878s user 0m6.863s sys 0m0.658s

  • Respondiendo a #7:
  • 8

    Avatar de gabrielon !

    "Mac Intel Core 2 Duo 2.4 4g ddr2 ram 800mhz x86_64" Esto .. si pongo a correr el C# en Windows lo flipas. Deja que Oscar lo pruebe en su Gentoo, cuando pueda :)

  • Respondiendo a #7:
  • 12

    Avatar de Oscar Campos !

    /usr/bin/time -f '%Uu %Ss %er CPU%P %MkB %w %C' java -Xms512m -Xmx1024m HashTest 2.05u 0.27s 0.90r CPU256% 1785072kB 168 java -Xms512m -Xmx1024m HashTest

  • 14

    interesante

    Avatar de blackt !
    blackt | 1 estrellas

    Error Fatal en C++.

    En C++ map es un arbol rojo-negro o un arbol auto-balanceado ,por que su complejidad es de O(log n) y una tabla hash como en los demas ejemplos es O(1).

    Por eso tarda mas C++ y es el que consume minimo de memoria.

    recomiendo ver los bench en http://shootout.alioth.debian.org/ aun que con un poco de cuidado ya que muchas veces se deforma el estilo de programar para obtener la mayor velocidad.

    Aun que por que go esta desarrollado por Google seria ver cual es el rendimiento en servidores,el nivel de abstraccion que logra ,el manejo de concurrencia y paralelismo.

  • Respondiendo a #14:
  • 17

    Avatar de Oscar Campos !

    Usando un hash_map:

    0.96u 0.16s 1.13r CPU99% 825312kB 1 ./cppbench

  • Respondiendo a #14:
  • 33

    Avatar de errepunto !
  • 15

    Avatar de maxx.es !

    a ver si con esos dos el "código equivalente en Go" se va a quedar "entre C y C++":

    C: float logs[5000000]; int main() { float i = 0; for(int j = 0; j < 5000000; ++j, ++i) logs[j] = log(i); return 0; }

    C++: #include int main() { vector logs; for(float i = 0; i < 5000000.; ++i) logs.push_back(log(i)); return 0; }

  • Respondiendo a #15:
  • 18

    Avatar de Oscar Campos !

    Sin usar contenedores de ningún tipo queda tal que así:

    0.27u 0.02s 0.29r 0:00.29 CPU99% 157920kB 1 ./gobench 

    0.20u 0.05s 0.25r 0:00.25 CPU99% 266592kB 1 ./cppbench 

    0.18u 0.01s 0.20r 0:00.20 CPU98% 79824kB 1 ./cbench

    -- editado por última vez a las 01:20

  • 16

    !
    | 1 estrellas

    Yo para la implementación de python usaría xrange en vez de range, siendo el primero, el doble de mas eficiente y mas rápido que el segundo:

    >>> timeit.Timer("""for i in xrange(1, 5000000): a = i""").timeit(10) 3.8110811710357666 

    >>> timeit.Timer("""for i in range(1, 5000000): a = i""").timeit(10) 6.158822774887085

    -- editado por última vez a las 01:00

  • Respondiendo a #16:
  • 19

    Avatar de Oscar Campos !

    CPython: 3.41u 0.32s 3.74r 0:03.74 CPU99% 1763536kB 1 python benchmark.py

    PyPy: 1.96u 0.37s 2.35r 0:02.35 CPU99% 2442256kB 1 pypy-c1.5 benchmark.py

  • Respondiendo a #16:
  • 32

    Avatar de errepunto !

    De hecho, en tu ejemplo, es 5 millones de veces más eficiente, jeje. Range crear un array con el número de elementos indicado, xrange es un generador. Esto es, una función que devuelve un valor cada vez que la llamas. Quizás ligeramente más lento, pero muchísimo más eficiente...

  • 20

    !
    | 1 estrellas

    En mi maquina que es bastante mas lenta y mas antigua que con la que probaste tu...

    He hecho unas cuantas pruebas rápidas del mismo algoritmo en javascript/nodejs y el resultados han sido algo llamativos:

    http://www.niwi.be/paste/25/ (Codigo de la prueba, similar a la de python)

    [niwi@vaio.niwi.be][/tmp/bench/javascript]% node bench.js

    1.596940040588379

  • 22

    !
    | 1 estrellas

    En si los micro benchmarks no dicen mucho pero es divertido indagar :) <.< >.>

    PD. [flame] Java Rules [/flame]

  • 23

    !
    | 1 estrellas

    Sin menospreciar tus pruebas hay un sitio dedicado a eso en el que puedes comprobar muchos datos, velocidad, uso de cpu, de memoria, tamaño del código fuente acerca de muchos lenguajes http://shootout.alioth.debian.org/

  • 24

    Avatar de juanpablogc !

    El uso de Hashtable es incorrecto para esto, hay que echar un vistazo a: http://blog.bodurov.com/Performance-SortedList-SortedDictionary-Dictionary-Hashtable/

    Aunque lo he probado asi a priori y ahora el Dictionary es más rapido que el Hashtable

    Aparte el uso de double en C# ¿por qué? tiene 16 digitos frente a float que tiene 7.

    Si tienes tiempo cambia el codigo con Dictionary y comentanos de nuevo a ver si alucionamos mas, aparte que podriamos hacerlo mas multicore (que el mono solito lo empieza (131%) :) ).

    static void Main(string[] args) { Dictionary dict = new Dictionary(5000000); Parallel.For(0,5000000,new ParallelOptions(){ MaxDegreeOfParallelism = 4}, i => { dict.Add(i, (float)Math.Log(i)); }); }

    Aqui puedes tomar la sobrecarga del For si quieres para probar con un core nada mas o varios. Para ello tienes que usar c# 3.0 de mono o superior.

    No se si aquí va por hilos o por cores, si eso ponle hasta 8, sería grato para todos saber estos datos ya que lo has trabajado tan bien.

  • 25

    Avatar de gabrielon !

    Fui yo quien propronia el uso de un double en vez de un float en C# para que la comparativa fuera mejor y ya que log(double d) requiere un double y evitar así un casting. La verdad es que no lo he probado, quizas incluso double esté sobrecargado y permita un float directamente o incluso un entero. Pero por probar ..

    Curioso lo de Parallel.For, no lo conocía y si había hecho multithreading alguna vez lo habia desarrollado a partir de la creación de nuevos threads de una forma semejante a esta:

    http://msdn.microsoft.com/en-us/library/aa645740%28VS.71%29.aspx

    Hoy ya he aprendido algo nuevo :)

  • 26

    Avatar de domi10 !
    domi10 | 1 estrellas

    Por lo general, está bien ver este tipo de pruebas. Pero no puede utilizar para C++ un map y para C# un hash, porque un hash hace las inserciones en tiempo constante (no siempre, pero puede que si) y el map hace las inserciones con eficiencia log base 2 de n. Quieras o no, eso va a variar bastante en el tiempo de ejecución. Por eso, yo creo que no puede ser una prueba válida, para que lo fuera, todos deberían tener igualdad de condiciones.

  • Respondiendo a #26:
  • 27

    Avatar de Oscar Campos !

    Ciertamente, con un hash_map el resultado es muy diferente:

    0.96u 0.16s 1.13r CPU99% 825312kB 1 ./cppbench

    Cuando pueda haré otro tipo de becnhmark más fiable añadiendo también Java y Ruby

  • 28

    Avatar de Gerardo !

    Las pruebas son increíblemente sesgadas. ¿Y eso de que haya algo más rápido que C que no sea ensamblador? La unidad de centésimas de segundo no parece muy fiable a la hora de comparar resultados.

    -- editado por última vez a las 13:42

  • Respondiendo a #28:
  • 31

    Avatar de Oscar Campos !

    Creo que no ha sido sutil la forma en la que he dicho en todo momento en el post que el benchmark es bastante chorra.

    De hecho en los primeros párrafos digo exactamente que el benchmark lo único que hace es devolver el logaritmo natural de i y meterlo en un hash o map con índice, vamos, que no estaba prometiendo un 3DMark ni nada de eso xD

  • 29

    Avatar de mapuka !
    mapuka | 1 estrellas

    Hace un tiempo en slashadot salió un paper de un empleado de Google (Robert Hundt) que hablaban del rendimiento y ganaba claramente C++. El enlace a Slashdot aquí y el directo al paper

    En dicho paper comparaban los lenguajes Go, C++, Scala y Java. Comparaban varias cosas como las líneas de código, el tamaño en memoria, el tiempo de compilación, el tamaño del binario o jar y el tiempo de ejecución. Go 6g era 7 veces más lento que C++ y Go Pro 5.5 veces más lento. El uso de memoria  por parte de Go era también peor.

    Las conclusiones respecto a Java, C++, Scala y Go os las dejo literalmente para que no se me acuse de manipular:

    C++: We find that in regards to performance, C++ wins out by a large margin. However, it also required the most extensive tuning efforts, many of which were done at a level of sophisti- cation that would not be available to the average programmer.

    Scala: Scala concise notation and powerful language features al- lowed for the best optimization of code complexity.

    Java: The Java version was probably the simplest to implement, but the hardest to analyze for performance. Specifically the effects around garbage collection were complicated and very hard to tune. Since Scala runs on the JVM, it has the same issues.

    Go: Go offers interesting language features, which also allow for a concise and standardized notation. The compilers for this language are still immature, which reflects in both performance and binary sizes.

    -- editado por última vez a las 16:02

  • Respondiendo a #29:
  • 30

    Avatar de Oscar Campos !

    Ese es precisamente el paper del que hablo en el post y esta es la respuesta a ese paper utilizando profiling para mejorar el rendimiento de Go utilizando los mismos tests de rendimiento.

    Saludos.

  • Respondiendo a #29:
  • 40

    Avatar de j0seant !

    Solo con el tiempo que tardan en cargar su máquina virtual Java o .NET el resto de esa tabla ya ha terminado el test xD los test siempre se pueden arrimar hacia donde uno quiera, pero lo que dice la práctica es que programas en Java o .NET a medida que crecen se arrastran y eso por no decir la ingente cantidad de recursos que consumen. Los Javeros dirán que es porque no está bien programado, pero es que en C/C++ no hay malos programadores o que ? ;)

  • 34

    Avatar de Dany Paredes !

    Para algunos "Es mas facil criticar, que aportar". :/ Que baina es con si el Benchmark esta bien o mal el chaval ha hecho un esfuerzo de que veamos la diferencias, en caso de que este mal en vez de criticarlo simplemente haga como algunos que han puesto sus reviews y sus ejemplos de codigo y ya !

  • 35

    !
    | 1 estrellas

    ¿Qué significa que C# utilice un 131% de la CPU??

  • Respondiendo a #35:
  • 38

    Avatar de charli_htp !

    Iba a preguntar lo mismo. Explicación quiero.

  • Respondiendo a #35:
  • 39

    Avatar de Oscar Campos !

    Que está usando más de un núcleo. Lo dice en el artículo.

  • 36

    Avatar de r-e-i-n-a !

    Hay dos formas de hacer un programa.

    Cuanta más memoria disponible haya, y más memoria utilicemos, más rápido (una vez cargado en memoria "el programa") funcionará el mismo, al poder cargar en memoria ciertos datos que también pueden ser obtenidos mediante algoritmos en el propio programa (¡qué importante es la optimización del código!).

    Se pueden llegar a dos soluciones iguales mediante argumentos diferentes, por ejemplo:

    - Más tiempo de CPU, menos uso de memoria 

    - Menos tiempo de CPU, más uso de memoria

    Teniendo en cuenta que un programa puede ser muy extenso, todas estas pequeñas décimas de segundo que se ganan o se pierden son acumuladas hasta tal punto que es notable.

    -- editado por última vez a las 17:54

  • Respondiendo a #36:
  • 41

    Avatar de Gerardo !
    Hay dos formas de hacer un programa.


    ¿Sólo hay dos formas de hacer un programa?

    -- editado por última vez a las 07:56

  • 37

    Avatar de errepunto !

    Me acabo de dar cuenta de otra cosa con el código en Python: es demasiado largo :D

    import math d = map(math.log, range(1, 500000))

    Usar la función map para aplicar una función a una lista de elementos es más eficiente que usar un bucle, porque internamente la función map utiliza un bucle en C super-optimizado. No lo digo yo, lo dice el Benevolente Dictador :)

    PD: Con este cambio, el programa python se ejecuta en casi la mitad de tiempo.

  • 42

    Avatar de juanpablogc !

    He realizado una serie de benchmarks basandome en el codigo de C# optimizando todo lo que he podido multicore y memoria, podeis echarle un vistazo en: http://mareinsula.wordpress.com/

  • 43

    Avatar de gabrielix82 !

    El primer comentario de blackt ya deberia dejar todo claro, aunque creo que muchos no entendieron. Como programador de C++: vector en vez de un map

    como programador de C: usas una biblioteca externa, que no es afectada por tu compilacion por lo tanto tampoco es optimizada, siendo el caso de gentoo podria estar optimizada dependiendo de tu USE flag.

    como usuario de Gentoo: deberias conocer a la perfeccion las optimizaciones de gcc.

    proba este version en la misma computadora y reveamos que parece: http://pastebin.com/j4d0Vu9m

Escribir un comentario

Para hacer un comentario es necesario que te identifiques: ENTRA o conéctate con Facebook Connect

Anunciate aquí

WSL Weblogs SL