Infra - Linux
Desempenho e portabilidade: GCJ o compilador Java Livre
Com a repercussão gerada quando a Sun resolveu disponibilizar o código fonte do Java, resolvi testar o Java Livre. O projeto GCJ da GNU é um compilador Java totalmente livre, onde o desenvolvedor pode gerar bytecode ou código binário nativo. Não sou especialista em Java, mas fiquei surpreso ao executar os testes mencionados neste artigo.
por Alessandro de Oliveira FariaO projeto GCJ é um compilador Java 100% livre no qual podemos gerar bytecodes ou binários nativos. Baseado em algumas pesquisas, cheguei a conclusão que existe suporte ao kit Java J2SE 1.4.2, mas não na API Swing. Mas acredito que esta não disponibilidade é apenas uma questão de tempo.
A Red Hat há algum tempo lançou uma versão do Eclipse que não depende da JVM, compilada com o GCJ, gera programas para execução nativa, como o compilador GCC. O Eclipse é um ambiente de desenvolvimento utilizado por programadores Java, C e C++.
Em aproximadamente em fevereiro de 2006, foi disponibilizada à comunidade a versão 4.1.0 do GCC com diversas mudanças.
O GCC possui front-ends para as linguagens C, C++, Objective C, Fortran, Java e Ada e suas respectivas bibliotecas. Sendo assim posso dizer que estamos mais próximo de um compilador livre para Java com capacidade de traduzir bytecodes ou código-fonte em Java para código executável nativo. Imagine a portabilidade do Java junto a performance do compilador C.
Instalação dos pacotes necessários:
Em minha distribuição SuSE bastou utilizar os pacotes gcc-java, libgcj e libgcj-devel, como no exemplo abaixo:
Para efeito de informação, a libgcj fornece para a aplicação os componentes em tempo de execução que seriam fornecidos pela JVM.
Compilando e testando um programa exemplo
Compilando um programa "OLA MUNDO".
Para compilar um programa em Java utilizamos o comando gcj. Abaixo alguns parâmetros utilizados na sintaxe de compilação:
- -o : Nome do arquivo binário a ser gerado;
- -c : Cria apenas o arquivo objeto;
- -O : Compila com otimizações;
- -g : Gera informações para o debug;
- --main=Nome-Classe : Nome da classe utilizada para iniciar o programa.
Para iniciar, crie um programa "OLA MUNDO" em Java para efetuarmos os primeiros testes de compilação. Abaixo o conteúdo do programa BemVindo.java. Para quem preferir o download pode ser efetuado aqui.
// Olá mundo em java. // Arquivo BemVindo.java. public class BemVindo { public static void main(String[] args) { System.out.println("Olá Mundo!"); } }
Agora compilaremos o nosso primeiro programa informando o nome do arquivo binário (BemVindo), a classe main e no nome do arquivo fonte.
Pronto! Após a compilação, basta executar o programa BemVindo como no exemplo abaixo:
$ gcj -o BemVindo --main=BemVindo BemVindo.java $ ./BemVindo Olá Mundo!
Gerando um bytecode com o programa "OLA MUNDO"
Para não gerar um código nativo e sim um bytecode, basta utilizar o parâmetro -C. O comando gij utiliza a biblioteca libgcj para proporcionar ao sistema uma máquina virtual. Vale à pena ressaltar que a variável ambiental CLASSPATH do Java é utilizada gij e gcj.
No exemplo abaixo geramos um bytecode e o executamos com o JVM da Sun e com o GIJ! Veja como é simples:
$ gcj -C BemVindo.java $ ls BemVindo.class BemVindo.class $ gij BemVindo Olá Mundo!
Agora teste o bytecode gerado como JVM do Java:
$ java BemVindo Olá Mundo!
Outro ponto importantíssimo é que tanto gcj quanto o gij conseguem utilizar pacotes JAR na compilação e na execução de programa. O GCJ possui um utilitário similar ao jar, o fastjar, escrito inteiramente em C.
Para compilar aplicações com várias classes, basta utilizar o parâmetro -c, logo após cria o binário. Veja no exemplo abaixo:
$ gcj -c Classe1.java $ gcj -c Main.java $ ls Classe1.java Classe1.o Main.java Main.o $ gcj -o programa1 main=Main Classe1.o Main.o $ ls programa1 Classe1.java Classe1.o Main.java Main.o $ ./programaTestando a performance (compactando um vídeo mpeg)
Escolhi um programa em Java que compacta um arquivo MPEG para testar a performance de execução. O principal motivo que levou a esta escolha foi a compactação que exige um pouco de cálculo e a leitura e gravação em disco (assim conseguindo obter resultado com I/O).
Baixe o programa Glauber Brilhante no Viva o Linux e descompacte com o programa unzip como no exemplo abaixo:
$ unzip Zip.zip Archive: Zip.zip inflating: Zip/Zipando.java
O programa efetua a compactação de um programa informado pelo teclado. Como o objetivo é verificar a performance, efetuei algumas alterações para o código assumir sempre determinados valores. Abaixo menciono as linhas que a serem alteradas.
Quem preferir adquirir o código já alterado, efetue o download aqui.
Para efeito de informação, explicarei passo a passo as alterações. Primeiro entre na pasta criada Zip e edite o programa Zipando.java.
$ cd Zip/ $ vi Zipando.java
Na linha 31 o programa solicita a digitação do nome do arquivo destino (arquivo zip a ser criado). Sendo assim comentei a linha 31 e atribui na linha 32 uma constante na variável SAIDA.
31 // saida = leia.readLine(); 32 saida = "video.zip";
Já na linha 55 o programa solicita a digitação do tipo de informação a ser compactada 1=arquivo e 2=pasta. Novamente comentei a linha 55 e atribui na linha 56 o retorno da constante 1.
55 //return leia.readLine(); 56 return "1";
Agora na linha 89 o programa solicita a digitação do nome do arquivo origem (nome caso utilizei o arquivo de vídeo tst.mpg). Então comentei a linha 89 e atribui na linha 90 uma constante na variável nome.
89 // nome = leia.readLine(); 90 nome ="tst.mpg";
Agora compile com o gcj, gij e com o javac o nosso programinha, execute com o comando time para analisarmos os resultados como no exemplo abaixo:
ATENÇÃO: Ressalto que executei o programa 2 vezes para não criar falsos resultados em função do cache de disco.
Compilando e executando com o Java:
$ javac Zipando.java $ time java Zipando Zipando.java Zipando arquivos ou pastas Digite o nome do arquivo a ser gerado: Selecione..compactacao de: 1. Arquivo 2. Pasta Opcao: Digite o nome do arquivo a ser zipado: Compactando: tst.mpg Arquivo zipado com sucesso! real 0m24.482s user 0m19.613s sys 0m1.380s Compilando e executando com o gcj: $ gcj -o Zipando --main=Zipando Zipando.java $ time ./Zipando Zipando.java Zipando arquivos ou pastas Digite o nome do arquivo a ser gerado: Selecione..compactacao de: 1. Arquivo 2. Pasta Opcao: Digite o nome do arquivo a ser zipado: Compactando: tst.mpg Arquivo zipado com sucesso! real 0m12.600s user 0m10.565s sys 0m1.172s Compilando com o gcj e executando com o gij: $ gcj -C Zipando.java $ time gij Zipando Zipando.java Zipando arquivos ou pastas Digite o nome do arquivo a ser gerado: Selecione..compactacao de: 1. Arquivo 2. Pasta Opcao: Digite o nome do arquivo a ser zipado: Compactando: tst.mpg Arquivo zipado com sucesso! real 0m13.225s user 0m9.365s sys 0m0.988s
Abaixo os resultados:
----------------------------- ! Execução ! Tempo ! ! Java bytecode ! 24.482s ! ! Código nativo ! 12.600s ! ! gij bytecode ! 13.225s ! -----------------------------
Quero deixar bem claro que o objetivo deste documento não é gerar polêmica, muito menos classificar como melhor ou pior determinada tecnologia, e sim disponibilizar os teste efetuados na NETi TECNOLOGIA junto a equipe de desenvolvimento e pesquisa da empresa.
Alessandro de Oliveria Faria (CABELO)
Analista de Negócios
http://www.netitec.com.br/alessandro
- Login automático com SSH e Automatização da instalação (deploy) e atualização de sites com GitLinux
- Extensão Sun Presentation Minimizer para Broffice.ORGLinux
- Otimização de Desempenho em sistemas GNU/LinuxLinux
- Hardware para sistemas GNU/Linux - Dicas de Desempenho - Parte 3Hardware
- Hardware para sistemas GNU/Linux - Dicas de Desempenho - Parte 2Hardware