Artigos com o marcador JRuby

Rails Summit Latin America 2008 – Excelente

Evento totalmente excelente.

Para quem esteve no evento sabe o que eu estou falando. Foi um evento muito, mas muito bom mesmo. As palestras de ltíssimo nível, bem organizado, local be acessível para que vem de fora e ainda com as “locawebzetes”. Fábio Akita e o pessoal da organização realmente estão de parabéns.

Dia 1

Fábio Akita abriu o evento e passou a palavra para Gilberto Mautner que é co-fundador da Locaweb. Esse é o cara que trouxe o Ruby on Rails para a Locaweb. Na abertura, tivemos um vídeo onde os dois loucos do RailsEnvy mandaram uma mensagem para o Rails Summit Latin America 2008. Vocês podem ver o vídeo aqui: http://vimeo.com/1974744

Sobre as palestras, no primeiro dia tivemos excelentes palestras com Chad Fowler falando sobre como ser reconhecido e como ser “remarkable” (be remarkable) com o que você faz. Esse assunto tanto cabe em desenvolvimento como em qualquer outra área profissional.

David Heinemeir Hanson (D.H.H) respondeu dúvidas e questões do pessoal a respeito (logicamente) do Ruby on Rails. Foram abordadas questões sobre Thread Safety, Internacionalização, Release do Rails 2.2 (a qual ele não revelou) entre outras.

Sobre Rest tivemos uma palestra muito legal com George Malamidis e Danilo Sato, ambos da ThoughtWorks.

Assisti também a palestra de Carlos Brando e a experiência dele e da equipe brasileira trabalhando para a SurgeWorks. Foi abordado assuntos bem interessantes como a aplicação de métodos ágeis com equipes remotas.

Tivemos um keynote de Chris Wanstrath criador do repositório GitHub um dos mais acessados pela comunidade Rails. Ele contou sobre a trajetória de sua vida profissional até chegar no GitHub.

E para finalizar o primeiro dia tivemos uma “desconferência” (Birds of a Feather) onde quem quisesse subir no palanque para falar o que queria sobre Ruby/Rails ou relacionado podia. Uma momento muito bom de descontração mesmo.

Nesse primeiro dia não tive a oportunidade de assistir algumas palestras pois eram paralelas com outras. Assim não poderei falar muito sobre as palestras do Fábio Akita e Dr.Nic.

Dia 2

Já logo pela manhã começamos com a palestra dos carinhas (Ninh Bui e Hongli Lai) da Phusion. Essa palestra foi excelente. A apresentação dos caras é sensacional. Falaram sobre passenger, escalabilidade, distribuição de carga…

Depois por áudio conferência, tivemos uma apresentação de Charles Nutter e Thomas Enebo que são criadores mantenedores do JRuby. Fizerem demonstração incríveis e como é fácil rodar aplicações Swing com JRuby e também alguns benchmarks com JRuby.

Fiquei curioso sobre a palestra de George Guimarães que falou sobre deployments e configuração de ambiente de produção para aplicações Rails. Ele também abordou algumas dificuldades que tiveram na construção da StartUp Pagestacker.

Para mim, as melhores palestras vieram nesse momento. As palestras de David Chelimsky sobre RSpec e sobre o Cucumber foram excelentes. Explicou os conceitos do BDD (Behavior Driven Development) e do TDD (Test Drive Development) além de mostrar exemplos reais da utilização do RSpec e do Cucumber. Fiquei honrado de poder assitir a palestra do David e espero poder assistir muitas outras.

Danilo Sato voltou no dia 2 (mas agora sem falar inglês e sem o George Malamidis) e também fez uma ótima apresentação sobre testes automatizados. Mostrou exemplos e problemas enfrentados no dia a dia do desenvolvedor na hora de elaborar testes.

Fabio Kung também palestrou no evento falando sobre o uso de JRuby porém mais focado na VM Java do que no código Ruby propriamente dito. Apresentou vantagens sobre o uso do JRuby ao invés do interpretador do Matz e exemplificou isso no uso de memória, e threads.

E para finalizar o ciclo de palestras no segundo dia tivemos o keynote de Obie Fernandez que falou com é dia a dia no desenvolvimento dos projetos de sua empresa Hashrocket onde eles usam métodos ágeis e Rails. Mostrou o que deve ser feito e quais as atitude a serem tomadas para se ter sucesso no desenvolvimento com Rails. Essa também foi uma das melhores palestras do dia.

Assim como no primeiro dia não consegui assistir a todas as palestras do dia devido as sessões paralelas então acabei perdendo as palestras de Jay Fields, Manoel Lemos, Vinícius Teles, Phillippe Hanrigou e Luis Lavena.

Depois tivemos alguns sorteios dos patrocinadores (Intel, Sun, Accept, Info Exame, Linux Magazine…) e da Locaweb. Saí do evento por volta das 20:45 e fiquei totalmente satisfeito com o que vi e aprendi. Valeu muito a pena o investimento. Se eu fosse você já começava a me preparar para o Rails Summit Latin America 2009. Eu já estou me preparando.

Fotos

Aqui segue alguns materiais “coletados” pela Net. Como eu sou uma anta e esqueci de levar máquina fotográfica, pegarei emprestado os Flickrs de algumas pessoas que foram ao evento:

Assim que eu conseguir mais materiais legais do evento eu com certeza postarei. Muitos palestrantes irão disponibilizar suas apresentações na Web, assim que eu descobrir onde elas ficarão eu também postarei.

Veja também o LiveStream do BlogBlogs.

  • Share/Bookmark

Rails Summit Latin America

Fala galera! Já faz um tempinho que não posto pois o trabalho está corrido. Vamos ver se daqui para frente volto apostar com mais frequência, tá difícil, mas vou tentar!

Bom, volto com esse post para divulgar o maior evento sobre Ruby on rails da América Latina que vai acontecer aqui no Brsil. Em São Paulo. É o Rails Summit Latin America. O evento promete e os palestrantes são de altíssimo nível. Mas muito alto mesmo, o próprio DHH, criador do framework, irá palestrar.

No blog do Akita há muitas informações sobre o evento, veja mais detalhes aqui:

A Locaweb está partocinando o evento e você pode fazer sua inscrição aqui:

No mesmo site da inscrição contém os valores, os palestrantes, o local… Tudo sobre o evento.

Eu já fiz a minha incrição e estarei lá com certeza. Você já fez a sua?

  • Share/Bookmark

Comparação de desempenho entre linguagens de programação

No dia 08/07/2008 o blog var/log/mind publicou uma comparação de desempenho entre algumas linguagens de programação. As linguagens testadas pelo blog foram C++, JAVA, Ruby, JRuby, Python, Jython, Groovy e PHP. Esse tema gerou até um bafafá na blogosfera nacional e internacional.

A tipo de benchmark feito pelo é blog foi bem simples e baseado em um pedaço de lógica onde é medido o tempo de cada iteração num total de 100000 iterações.

O mais espantoso foi que JAVA obteve um desempenho melhor do que C++. Esse resultado me deixou com uma pulga atrás da orelha porque sempre acreditei (mas nunca havia testado) de que C++ por ser somente compilado seria bem mais rápido do que JAVA que é compilado e interpretado pela JVM.

Então resolvi fazer o mesmo teste que o blog var/log/mind fez. Utilizei os mesmos códigos disponibilizados por ele e rodei eles em minha máquina. Somente não testei Python, Jython e o Groovy.

Ambiente de Testes

Meu ambiente de testes difere do ambiente de testes do var/log/mind (veja a tabela mais abaixo), assim como versões de compiladores e interpretadores. Abaixo segue o meu ambiente de testes e mais um pouco abaixo as versões dos compiladores e interpretadores usados no teste.

Meu ambiente:

  • Processador: AMD 4200+ X2 64 Bits
  • Memória: 3GB RAM
  • SO: Windows XP SP2 Professional

As diferenças entre o ambiente de teste original do var/log/mind e o meu ambiente de teste:

MeuPost.com var/log/mind
Processador AMD 4200+ X2 64 Bits Intel® Core™ Duo CPU T2600 @ 2.16GHz
Memória 3GB RAM 2GB
SO: Windows XP SP2 Professional Ubuntu Gutsy Gibbon 7.10

Compiladores e Interpretadores usados:

  • C++: MinGW32 GCC: 3.4.2
  • JAVA 1.6
  • Ruby 1.8.6-26
  • JRuby 1.1
  • PHP 5.2.3

Teste:

Para realizar o teste rodei 5 vezes o código de cada linguagem diferente e anotei todos os resultados em nanossegundos. Depois tirei a média dos resultados.

Resultados

Seguinte a tendência dos resultados, em meu ambiente JAVA também foi superior ao C++. Os resultados também mostraram que o Python está mais maduro que Ruby embora nas últimas versões do Ruby (1.9) o desempenho tenha melhorado muito.

Outro fato interessante é que o JRuby está também mais rápido que Ruby. Já o PHP mostra a força de sua maturidade e popularidade ganhando tanto do Ruby como do JRuby, isso em meu ambiente, porque no var/log/mind tanto o Ruby como o JRuby ganharam do PHP.

Acredito que esse desempenho superior do Ruby no var/log/mind está diretamente associado ao sistema operacional. O Ruby está rodando muito mais rápido em ambientes Linux do que em Windows.

Abaixo segue a tabela de resultados:

Iteração 1 Iteração 2 Iteração 3 Iteração 4 Iteração 5 Média Total
C++ 12000 12000 12000 12000 12000 12000 60000
Java 1509 1369 1384 1376 1385 1404,6 7023
Ruby 491990 493750 494690 493280 494840 444232 2468550
Jruby 244040 246360 243830 243450 246750 244886 1224430
PHP 125200 125030 124880 124890 124900 124980 624900
1 segundo = 1000000 microssegundo = 1000000000 nanossegundo

Para facilitar a visualização dos resultados, abaixo segue um gráfico com o resultado do teste:

Desempenho das Linguagens de Programação

Códigos

Abaixo segue os códigos utilizados nos testes. São os mesmos do var/log/mind com uma única diferença no código C++. Como o var/log/mind usou o Linux, ele usou a função gettimeofday(), em Windows essa função não existe, então eu como não sou um programador C++, achei essa função no Blog OpenAsthra e coloquei no código.

Todos os outros códigos são exatamente iguais.

C++

#include <time.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
 
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif
 
struct timezone 
{
  int  tz_minuteswest; /* minutes W of Greenwich */
  int  tz_dsttime;     /* type of dst correction */
};
 
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag = 0;
 
  if (NULL != tv)
  {
    GetSystemTimeAsFileTime(&ft);
 
    tmpres |= ft.dwHighDateTime;
    tmpres <<= 32;
    tmpres |= ft.dwLowDateTime;
 
    tmpres /= 10;  /*convert into microseconds*/
    /*converting file time to unix epoch*/
    tmpres -= DELTA_EPOCH_IN_MICROSECS; 
    tv->tv_sec = (long)(tmpres / 1000000UL);
    tv->tv_usec = (long)(tmpres % 1000000UL);
  }
 
  if (NULL != tz)
  {
    if (!tzflag)
    {
      _tzset();
      tzflag++;
    }
    tz->tz_minuteswest = _timezone / 60;
    tz->tz_dsttime = _daylight;
  }
 
  return 0;
}
 
#define TEST
#ifdef TEST
#endif
 
class Person
{
 
    public:
 
        Person(int count) : _next(NULL), _prev(NULL) { _count = count; }
        int shout(int shout, int nth)
        {
            if (shout < nth) return (shout + 1);
            _prev->_next = _next;
 
            _next->_prev = _prev;
            return 1;
        }
        int count() { return _count; }
        Person* next() { return _next; }
        void next(Person* person) { this->_next = person ; }
        Person* prev() { return _prev; }
        void prev(Person* person) { this->_prev = person; }
    private:
        int _count;
        Person* _next;
        Person* _prev;
};
 
class Chain
{
    public:
        Chain(int size) : _first(NULL)
        {
            Person* current = NULL;
            Person* last = NULL;
            for(int i = 0 ; i < size ; i++)
            {
                current = new Person(i);
                if (_first == NULL) _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 = 1;
            while(current->next() != current)
            {
                Person* tmp = current;
                shout = current->shout(shout,nth);
                current = current->next();
                if (shout == 1)
                {
                    delete tmp;
                }
            }
            _first = current;
            return current;
        }
        Person* first() { return _first; }
    private:
        Person* _first;
};
 
int main(int argc, char** argv)
{
    int ITER = 100000;
    Chain* chain;
    struct timeval start, end;
    gettimeofday(&start,NULL);
    for(int i = 0 ; i < ITER ; i++)
    {
        chain = new Chain(40);
        chain->kill(3);
        delete chain;
    }
    gettimeofday(&end,NULL);
    fprintf(stdout,"Time per iteration = %d microsecondsnr", (((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec)) / ITER);
    //fprintf(stdout,"Last man standing is %dnr", (chain->first()->count() + 1));
    return 0;
}
 
}

JAVA:

package com.dnene.josephus;
 
public class Chain {
 
	private Person first = null;
 
	public Chain(int size) {
		Person last = null;
		Person current = null;
 
		for (int i = 0; i < size; i++) {
			current = new Person(i);
 
			if (first == null)
				first = current;
 
			if (last != null) {
				last.setNext(current);
				current.setPrev(last);
			}
 
			last = current;
		}
 
		first.setPrev(last);
		last.setNext(first);
	}
 
	public Person kill(int nth) {
		Person current = first;
		int shout = 1;
 
		while (current.getNext() != current) {
			shout = current.shout(shout, nth);
			current = current.getNext();
		}
 
		first = current;
 
		return current;
	}
 
	public Person getFirst() {
		return first;
	}
 
	public static void main(String[] args) {
 
		int ITER = 100000;
		long start = System.nanoTime();
 
		for (int i = 0; i < ITER; i++) {
			Chain chain = new Chain(40);
			chain.kill(3);
		}
 
		long end = System.nanoTime();
 
		System.out.println("Time per iteration = " + ((end - start) / (ITER))
				+ " nanoseconds.");
	}
}
 
package com.dnene.josephus;
 
public class Person {
 
	int count;
	private Person prev = null;
	private Person next = null;
 
	public Person(int count) {
		this.count = count;
	}
 
	public int shout(int shout, int deadif) {
		if (shout < deadif)
			return (shout + 1);
 
		this.getPrev().setNext(this.getNext());
		this.getNext().setPrev(this.getPrev());
 
		return 1;
	}
 
	public int getCount() {
		return this.count;
	}
 
	public Person getPrev() {
		return prev;
	}
 
	public void setPrev(Person prev) {
		this.prev = prev;
	}
 
	public Person getNext() {
		return next;
	}
 
	public void setNext(Person next) {
		this.next = next;
	}
}

Ruby / JRuby

class Person
    attr_reader :count, :prev, :next
    attr_writer :count, :prev, :next
 
    def initialize(count)
        #puts 'Initializing person : ' + count.to_s()
        @count = count
        @prev = nil
        @next = nil
    end
 
    def shout(shout, deadif)
        if shout < deadif
            return shout + 1
        end
        @prev.next = @next
        @next.prev = @prev
        return 1
    end
end      
 
class Chain
    attr_reader :first
    attr_writer :first
 
    def initialize(size)
        @first = nil
        last = nil
        for i in (1..size)
            current = Person.new(i)
            if @first == nil
                @first = current
            end
            if last != nil
                last.next = current
                current.prev = last
            end
            last = current
        end
        @first.prev = last
        last.next = @first
    end
 
    def kill(nth)
        current = @first
        shout = 1
        while current.next != current
            shout = current.shout(shout,nth)
            current = current.next
        end
        @first = current
        return current
    end
end
 
ITER=100000
start = Time.now
ITER.times { |i|
chain = Chain.new(40)
chain.kill(3)
}
ends = Time.now
puts 'Time per iteration = ' + ((ends - start) * 1000000 / ITER).to_s() + " microseconds"

PHP

<?php
class Person
{   
    function __construct($c)
    {   
        $this->count = $c;
    }       
 
    function getPrev()
    {       
        return $this->prev; 
    }           
 
    function setPrev($pr)
    {   
        $this->prev = $pr;
    }   
 
    function getNext()
    {
        return $this->next;
    }
 
    function setNext($nxt)
    {
        $this->next = $nxt;
    }
 
    function shout($shout, $nth)
    {
        if ($shout < $nth)
        {
            return $shout + 1;
        }
        $this->getPrev()->setNext($this->getNext());
        $this->getNext()->setPrev($this->getPrev());
        return 1;
    }
}
 
class Chain
{
    var $first;
 
    function __construct($size)
    {
        for($i = 0; $i < $size ; $i++)
        {
            $current = new Person($i);
            if ($this->first == null) $this->first = $current;
            if ($last != null)
            {
                $last->setNext($current);
                $current->setPrev($last);
            }
            $last = $current;
        }
        $this->first->setPrev($last);
        $last->setNext($this->first);
    }
 
    function kill($nth)
    {
        $current = $this->first;
        $shout = 1;
        while($current->getNext() !== $current)
        {
            $shout =  $current->shout($shout,$nth);
            $current = $current->getNext();
        }
        $this->first = $current;
    }
}
 
$start = microtime(true);
$ITER = 100000;
for($i = 0 ; $i < $ITER ; $i++)
{
    $chain = new Chain(40);
    $chain->kill(3);
}
$end = microtime(true);
printf("Time per iteration = %3.2f microsecondsnr",(($end -  $start) * 100000 / $ITER));
?>

É isso pessoal.

Esse tema de desempenho sempre gera polêmica pois sempre há brechas e margens para discussão. Então, quem quiser debater sobre o assunto.

Até a próxima.

  • Share/Bookmark