Publicidad

RSS Google

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 LinuxArquitectura: x86_64Procesador: Intel® Core™ i7 CPU @ 2.80GHzVelocidad RAM: 1666

LenguajeTiempo UsuarioTiempo SistemaTiempo RealUso de CPUUso de RamCambios de ContextoC1.90s0.27s2.19s99%1826704kB1C++4.07s0.14s4.24s99%941808kB1C#1.72s0.29s2.01s131%2032176kB1155Python CPython 2.7.23.43s0.37s3.86s99%2101312kB1Python PyPy-c1.51.57s0.33s2.70s99%2442032kB280Go2.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 ContextoGo0.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 ContextoC0.31s0.00s0.31s99%1824kB1Go0.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

Cómo manejar Git como un experto desde Android Studio

5 Comentarios
Cómo manejar Git como un experto desde Android Studio

Hoy en día no nos imaginamos el desarrollo de un proyecto de software que no incluya un control de versiones, entre las diferentes opciónes para un VCS, Git, sin duda, se ha posicionado favorablemente por delante de otros grandes como Subversion y Mercurial.

La curva de aprendizaje que este tipo de herramientas suele implicar suele ser bastante alta, ya que la gran variedad de características y opciones que incluyen lo convierten en recursos complejos a la vez de muy potentes.

Leer más »

Polymer Day: profundizando en el uso de Polymer en proyectos reales junto a expertos en esta tecnología

2 Comentarios
Polymer Day: profundizando en el uso de Polymer en proyectos reales junto a expertos en esta tecnología

Aprovechando la ocasión de la celebración del primer evento en España centrado en Polymer, el Polymer Day. Hemos contactado con parte de la organización, entre ellos Reinaldo Aguilera y Jorge del Casar para hablar sobre Polymer, su importancia y cómo ellos ven el futuro y presente. Además de darnos algunas pildoras de lo que nos vamos a encontrar en el evento, un día y medio para hablar sobre Web Components con más de 10 charlas con desarrolladores que han usado Polymer en proyecto reales. Una oportunidad única.

Leer más »
Publicidad

Mejora tu código Java usando Groovy

20 Comentarios
Mejora tu código Java usando Groovy

¿Y por qué querríamos mejorar nuestro código Java? Seguro que en más de una ocasión escribiendo Java has pensado que es muy verboso o que seguro que tiene que haber una forma más fácil y sencilla de hacer esto. En ese caso, Groovy es para ti.

Apache Groovy es un lenguaje dinámico, opcionalmente tipado, con posibilidad de tipado y compilación estáticos para la JVM. Tiene como objetivo multiplicar la productividad de los desarrolladores gracias a una sintaxis concisa, familiar y fácil de aprender. Se integra sin problemas con cualquier programa Java e inmediatamente proporciona a una aplicación poderosas características como scripting, DSLs, metaprogramación en runtime y compile-time y programación funcional.

Leer más »

Android Studio 2.2 lleva el desarrollo de Android a un nuevo nivel

6 Comentarios
Android Studio 2.2 lleva el desarrollo de Android a un nuevo nivel

Algunos recordamos con dolor aquellos días en los que teníamos que usar Eclipse para desarrollar aplicaciones en Android. El cambio a Android Studio y la introducción de Gradle supusieron un innumerable número de mejoras y de flexibilidad que aún a día de hoy sigue dando sus frutos.

El nuevo Android Studio 2.2 presentado durante el Google I/O ha querido ir más allá, ofreciendo una gran cantidad de herramientas que facilitarán mucho el día a día de los programadores Android.

Hemos podido ver mejoras a nivel de diseño, desarrollo, compilación y testing, de las que paso a hablarte una a una.

Leer más »

Migraciones al cloud en primera persona

11 Comentarios
Migraciones al cloud en primera persona

El paradigma de gestión de infraestructura en el cloud y las razones que pueden haber detrás del mismo, son temas que habitualmente se pueden afrontar de una forma más sencilla y operativa en el núcleo de una startup o incluso de una empresa tradicional, mientras que en el ámbito de las administraciones públicas esto puede suponer "todo un reto".

Este reto es el que ha afrontado la Universitat Jaume I de Castellón en su paso de un entorno de gestión on-premises a uno totalmente gestionado en el cloud de Amazon y que hoy os relatamos como la primera experiencia de migración al cloud de una administración pública en españa.

No todo va a ser como Netflix o LinkedIn gestionan su infraestructura :)

Leer más »
Publicidad

Oracle le pide 9 mil millones a Google, por licencias de Java

5 Comentarios
Oracle le pide 9 mil millones a Google, por licencias de Java

Oracle y Google andan enredados en una incruenta batalla legal desde el 2012, por el uso por parte de esta última de 37 APIS de Java que se utilizan dentro del sistema operativo Android.

Es más, el problema no viene tanto del uso, si no del modo en que las utiliza. Ya que Google defiende que ha realizado un "uso razonable", como permite la licencia de forma gratuita. Mientras que Oracle defiende que debería estar recibiendo millones de dolares a causa del copyright.

Leer más »

MaterialDoc, en castellano los tutoriales de cómo implementar y usar los componentes de Material Design en Android

2 Comentarios
MaterialDoc, en castellano los tutoriales de cómo implementar y usar los componentes de Material Design en Android

Tanto si eres un desarrollador recién llegado a Android o un veterano programador seguramente has sufrido la tremenda desconexión entre las guías de diseño sobre Material Design de Google y la documentación para desarrolladores. Es decir, la carencia de un guía clara de cómo se implementa en código.

Para intentar solventar este problema surgió la iniciativa de MaterialDoc de la mano de Dmytro Danylyk, tratando de describir cómo usar y customizar los componentes de Material. Ahora llega su versión en castellano con los tutoriales originales traducidos y las aportaciones de las comunidad hispana de Android.

Leer más »

GDG Spain: entre las comunidades de desarrolladores más activas

5 Comentarios
GDG Spain: entre las comunidades de desarrolladores más activas

España cuenta con una de las comunidades de GDGs (Grupo de Desarrolladores de Google) más importantes a nivel mundial, con más de 150 eventos anuales organizados entre los más de 30 grupos de desarrolladores. España es el cuarto país a nivel mundial donde más movimiento se produce, y aspira a ser mucho más elevado. Los integrantes son libres de proponer cualquier tema, y por supuesto, es el lugar idóneo para compartir tecnologías como Android, Polymer, HTML5, Cloud, Go o cualquiera de las APIs de Google en su programa para desarrolladores.

Recientemente se organizó el evento que aglutina a los organizadores, el GDG Summit, allí se han sentado las bases para seguir creciendo y ser aún más útil a la comunidad de desarrolladores. Para dar a conocer la labor que realizan las distintas comunidades, el GDG Spain ha abierto una nueva web que aglutina los eventos, experiencias y conocimientos de los distintos colaboradores y organizadores. Una apuesta de comunicación para dar visibilidad y fomentar la participación.

Leer más »
Publicidad

Ver más artículos