Secciones

Artículos para tus primeros pasos

Si estás empezando a introducirte en el mundo de Groovy y Grails, no te pierdas nuestros artículos básicos: 

Entrevistas con los expertos
 

Los protagonistas te cuentan de qué van los proyectos más importantes del mundo Groovy:


Un proyecto de:
ImaginaWorks
Campus Escuela de Groovy

Groovy: primeros pasos

Benchmark de Groovy, Java, C++, etc.

idecasso - viernes 05/12/2008
Acabo de encontrar un benchmark de Java, C++, Groovy, Ruby, JRuby, Python, Jython, Php, etc.

http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/

En los resultados, aparece Groovy como el lenguaje mas lento, pero como siempre, baje el código y me di cuenta habian omitido todos los tipos de datos.
Por lo cual procedi a cambiar todos los def por el tipo de dato correspondiente y especificando que los enteros son int (0i, 5i,7i) y long donde tocaba, disminuyendo considerablemente el tiempo de ejecución.

En mi humilde Pentium 4 a 2.4 Ghz(no es dual Core), con 1.5 Gb de ram y Xubuntu 8.04, con sun jdk 1.6_07 y Groovy 1.5.6, para mas informacion es una Dell Optiplex GX260, en ella me dio los siguientes resultados:

Original 2178.45578797 microseconds (Interpretado)
Original 2130.03473054 microseconds (Compilado)
Corregido: 193.14217284 microseconds(Interpretedo)
Corregido: 191.73054723 microseconds(Compilado)

Pero luego pense en probar dejando los def y unicamente corrigiendo los enteros(int y long en la variable y 7i,5i,10i,7l) y los resultados fueron los siguientes:
Corregido int: 193.1019066 microseconds(Interpretedo)
Corregido int: 196.70635049 microseconds(Compilado)

El chiste del benchmark es que implementan el mismo algoritmo en diferentes lenguajes, siendo el resultado de Java "Puro":

Java: 2809 nanoseconds.

Lo que noto es que es un algoritmo que hace varios operaciones que no se implementarian directamente en Groovy, pero podemos observar que se corrijio bastante el desempeño cuando se dejo de usar def para los numeros enteros, tal vez este es el mayor cuello de botella de Groovy.

Y de hecho me parece que se acerca muchisimo a los demás lenguajes que siguen a C++ y Java, comparando los resultados del blogger contra los de mi máquina, tal vez en la suya Groovy quedaria en tercer lugar. Y yo no use Groovy 1.6, que si lo usaron en el benchmark.

Lo que aprendi es que hay que tener cuidado al usar def, evitar sobre todo al trabajar con numeros.

Este el código original:

class Chain  
{  
    def size  
    def first  
 
    def init(siz)  
    {  
        def last  
        size = siz  
        for(def i = 0 ; i < siz ; i++)  
        {  
            def current = new Person()  
            current.count = i  
            if (i == 0) first = current  
            if (last != null)  
            {  
                last.next = current  
            }  
            current.prev = last  
            last = current  
        }  
        first.prev = last  
        last.next = first  
    }  
 
    def kill(nth)  
    {  
        def current = first  
        def shout = 1  
        while(current.next != current)  
        {  
            shout = current.shout(shout,nth)  
            current = current.next  
        }  
        first = current  
    }  
}  
 
class Person  
{  
    def count  
    def prev  
    def next  
 
    def shout(shout,deadif)  
    {  
        if (shout < deadif)  
        {  
            return (shout + 1)  
        }  
        prev.next = next  
 
        next.prev = prev  
        return 1  
    }  
}  
 
def main(args)  
{  
    println "Starting"  
    def ITER = 100000  
    def start = System.nanoTime()  
    for(def i = 0 ; i < ITER ; i++)  
    {  
        def chain = new Chain()  
        chain.init(40)  
        chain.kill(3)  
    }  
    def end = System.nanoTime()  
    println "Total time = " + ((end - start)/(ITER * 1000)) + " microseconds"  
}  
 
def ITER = 100000  
def start = System.nanoTime()  
for(def i = 0 ; i < ITER ; i++)  
{  
    def chain = new Chain()  
    chain.init(40)  
    chain.kill(3)  
}  
def end = System.nanoTime()  
println "Time per iteration = " + ((end - start)/(ITER * 1000)) + " microseconds"



Código sin def:


class Chain
{
    int size
    Person first

    Person init(int siz)
    {
        Person last
        size = siz
        for(int i = 0i ; i < siz ; i++)
        {
            Person current = new Person()
            current.count = i
            if (i == 0i) first = current
            if (last != null)
            {
                last.next = current
            }
            current.prev = last
            last = current
        }
        first.prev = last
        last.next = first
    }

    Person kill(int nth)
    {
        Person current = first
        int shout = 1i
        while(current.next != current)
        {
            shout = current.shout(shout,nth)
            current = current.next
        }
        first = current
    }
}

class Person
{
    def count
    Person prev
    Person next

    def shout(shout,deadif)
    {
        if (shout < deadif)
        {
            return (shout + 1i)
        }
        prev.next = next

        next.prev = prev
        return 1i
    }
}

def main(args)
{
    println "Starting"
    long ITER = 100000l
    long start = System.nanoTime()
    for(int i = 0i ; i < ITER ; i++)
    {
        def chain = new Chain()
        chain.init(40i)
        chain.kill(3i)
    }
    long end = System.nanoTime()
    println "Total time = " + ((end - start)/(ITER * 1000i)) + " microseconds"
}

int ITER = 100000l
long start = System.nanoTime()
for(int i = 0i; i < ITER ; i++)
{
    Chain chain = new Chain()
    chain.init(4i)
    chain.kill(3i)
}
long end = System.nanoTime()
println "Time per iteration = " + ((end - start)/(ITER * 1000i)) + " microseconds"


Código con int y long corregidos únicamente, lo demás usa def:


class Chain
{
    int size
    def first

    def init(int siz)
    {
        def last
        size = siz
        for(int i = 0i ; i < siz ; i++)
        {
            def current = new Person()
            current.count = i
            if (i == 0i) first = current
            if (last != null)
            {
                last.next = current
            }
            current.prev = last
            last = current
        }
        first.prev = last
        last.next = first
    }

    def kill(int nth)
    {
        def current = first
        int shout = 1i
        while(current.next != current)
        {
            shout = current.shout(shout,nth)
            current = current.next
        }
        first = current
    }
}

class Person
{
    int count
    def prev
    def next

    int shout(shout,deadif)
    {
        if (shout < deadif)
        {
            return (shout + 1i)
        }
        prev.next = next

        next.prev = prev
        return 1i
    }
}

def main(args)
{
    println "Starting"
    long ITER = 100000l
    long start = System.nanoTime()
    for(int i = 0i ; i < ITER ; i++)
    {
        def chain = new Chain()
        chain.init(40i)
        chain.kill(3i)
    }
    long end = System.nanoTime()
    println "Total time = " + ((end - start)/(ITER * 1000i)) + " microseconds"
}

int ITER = 100000l
long start = System.nanoTime()
for(int i = 0i; i < ITER ; i++)
{
    def chain = new Chain()
    chain.init(4i)
    chain.kill(3i)
}
long end = System.nanoTime()
println "Time per iteration = " + ((end - start)/(ITER * 1000i)) + " microseconds"

Re: Benchmark de Groovy, Java, C++, etc.

idecasso - viernes 05/12/2008

Revisando otra vez el benchmark, me parecio que si verificaba con el profiler de Netbeans podria identificar los cuellos de botella, de hecho encontre que el 40% del tiempo de ejecución se iba en llamados a get y set, cosa que me parecio extraña por que no deberian tardar tanto, pero en fin, es un punto a tener en cuenta.

Probe poniendo como public todas los atributos de person y las llamadas a get y set bajaron a 36%, pero seria cosa de checar en donde mas habria que mover para obtener mejores tiempos.

Más que nada este asunto me interesa para poder saber como obtener mejor rendimiento en Groovy, que evitar o usar poco, y si mi aplicacion corre lenta por que es eso.

Aunque como dije antes, este es un algoritmo que se implementaria en Java y no en Groovy, por que el conjunto de datos es muy grande.

Re: Benchmark de Groovy, Java, C++, etc.

idecasso - viernes 05/12/2008

Revisando otra vez el benchmark, me parecio que si verificaba con el profiler de Netbeans podria identificar los cuellos de botella, de hecho encontre que el 40% del tiempo de ejecución se iba en llamados a get y set, cosa que me parecio extraña por que no deberian tardar tanto, pero en fin, es un punto a tener en cuenta.

Probe poniendo como public todas los atributos de person y las llamadas a get y set bajaron a 36%, pero seria cosa de checar en donde mas habria que mover para obtener mejores tiempos.

Más que nada este asunto me interesa para poder saber como obtener mejor rendimiento en Groovy, que evitar o usar poco, y si mi aplicacion corre lenta por que es eso.

Aunque como dije antes, este es un algoritmo que se implementaria en Java y no en Groovy, por que el conjunto de datos es muy grande.

Responder al hilo | Volver al foro "Groovy: primeros pasos" | Volver a los foros