Java para Desktop ou WEB eis a questão?

bom, o robozinho que ta em marte é programado em java!

[quote=fzampa]
Ps.: Me confirmem essa. É verdade que na NASA só programam em Assembler? Dizem que é confiável, e tals…[/quote]

É mentira! Posso afirmar com toda segurança do mundo, apesar de estar muito distante de conhecer os processos de desenvolvimento de software da NASA. Segue:

i) Assembly não é uma linguagem de programação;
ii) Assembly é uma linguagem de montagem (lembra das suas aulas de SW Básico? o compilador que vc implementou deveria gerar código de montagem…);
iii) Assembly não é produtivo e é impossivel implementar um simulador de um onibus espacial usando só assembly! [o nível de abstração é muito baixo];
iv) Logo, a NASA usa várias tecnologias e desenvolve tecnologias também;

[quote=microfilo]para quem acha que java é lento para desktop:
http://www.portaljava.com/home/modules.php?name=Forums&file=viewtopic&t=13257[/quote]

Sobre este mini-benchmark, eu resolvi encarar o desafio e implementar o teste Java vs. C# (insônia, tédio e cafeína resultam nestas coisas).
Aí vão os códigos (a versão Java é cópia ipsis-literis da versão original publicada no PortalJava, url acima).

//Java
public class QuicksortTest {
    
    private static final int SIZE = 1000000;

    public static void main(String[] args) {
        int array[] = new int[SIZE];
        long beginFill = System.currentTimeMillis();
        for (int i = 0; i < SIZE; i++) {
            array[i] = i % 100;
        }
        long endFill = System.currentTimeMillis();
        long beginSort = System.currentTimeMillis();        
        quicksort(0, SIZE - 1, array);
        long endSort = System.currentTimeMillis();
        System.out.println("Preenchimento de array: "+(endFill - beginFill)+" ms");
        System.out.println("Ordenação de array: "+(endSort - beginSort)+" ms");
        
    }
    
    public static void quicksort(int p, int q, int array[]) {
        if (p < q) {
            int j = p - 1;
            int aux = array[q];
            for (int i = p; i <= q; i++) {
                if (array[i] <= aux) {
                    int taux = array[i];
                    array[i] = array[++j];
                    array[j] = taux;
                }
            }
            quicksort(p, j - 1, array);
            quicksort(j + 1, q, array);
        }
    } 
}
//C#
using System;


namespace GUJ
{
	class Quicksort
	{
		
		private const int SIZE = 1000000;

		[STAThread]
		static void Main(string[] args)
		{			
			int[] array = new int[SIZE];
			DateTime beginFill = DateTime.Now;
			for (int i = 0; i < SIZE; i++){
				array[i] = i % 100;
			}
			DateTime endFill = DateTime.Now;
			DateTime beginSort = DateTime.Now;
			quicksort(0, SIZE - 1, array);
			DateTime endSort = DateTime.Now;
			Console.WriteLine("Preenchimento: {0}", endFill.Subtract(beginFill));
			Console.WriteLine("Ordenação: {0}", endSort.Subtract(beginSort));
			Console.ReadLine();
		}

		public static void quicksort(int p, int q, int[] array)
		{
			if (p < q)
			{
				int j = p - 1;
				int aux = array[q];
				for (int i = p; i <= q; i++)
				{


					if (array[i] <= aux)
					{
						int taux = array[i];
						array[i] = array[++j];
						array[j] = taux;
					}
				}
				quicksort(p, j - 1, array);
				quicksort(j + 1, q, array);
			}
		}

	}
}

Usando tanto Sun JVM 1.4.2_06 e 1.5.0, o código na versão Java lançou um StackOverflowError e não executou. O mesmo para a versão C# executada sobre o .NET Framework versões 1.0.37 e 1.1.24.

Agora, já que eu não estava tãooooooo disposto assim para consertar o quicksort do colega Felipe, resolvi brincar de avaliar qual API implementa um mecanismo de ordenação de arrays mais decente.
Para tanto, eu usei a classe java.util.Arrays, para o exemplo usando Java e a classe System.Array para o exemplo usando C#. Os códigos:

//Java
import java.util.Arrays;
public class ArraySortingTest {
    
    private final static int SIZE = 1000000;

    public static void main(String[] args) {
        int array[] = new int[SIZE];
        long beginFill = System.currentTimeMillis();
        for (int i = 0; i < SIZE; i++) {
            array[i] = i % 100;
        }
        long endFill = System.currentTimeMillis();
        long beginSort = System.currentTimeMillis();        
        Arrays.sort(array);
        long endSort = System.currentTimeMillis();
        System.out.println("Preenchimento de array: "+(endFill - beginFill)+" ms");
        System.out.println("Ordenação de array: "+(endSort - beginSort)+" ms");
    }
}
//C#
using System;
namespace GUJ
{
	class ArraySorting
	{
		
		private const int SIZE = 1000000;

		[STAThread]
		static void Main(string[] args)
		{			
			int[] array = new int[SIZE];
			DateTime beginFill = DateTime.Now;
			for (int i = 0; i < SIZE; i++){
				array[i] = i % 100;
			}
			DateTime endFill = DateTime.Now;
			DateTime beginSort = DateTime.Now;
			Array.Sort(array);
			DateTime endSort = DateTime.Now;
			Console.WriteLine("Preenchimento: {0}", endFill.Subtract(beginFill));
			Console.WriteLine("Ordenação: {0}", endSort.Subtract(beginSort));
			Console.ReadLine();
		}

	}
}

Resultados foram:
:arrow: JVM 1.4.2 (Client): Preenchimento = 50ms | Ordenação = 150ms
:arrow: JVM 1.4.2 (Server): Preenchimento = 30ms | Ordenação = 210ms
:arrow: JVM 1.5.0 (Client): Preenchimento = 40ms | Ordenação = 130ms
:arrow: JVM 1.5.0 (Server): Preenchimento = 20ms | Ordenação = 195ms
:arrow: .NET Framework 1.0: Preenchimento = 40ms | Ordenação = 320ms
:arrow: .NET Framework 1.1: Preenchimento = 50ms | Ordenação = 280ms

Tirem suas conclusões.

(Ambiente de execução: Athlon XP 2800+, 512Mb Ram, Windows XP SP2)

P.S.: Desconsiderei o startup-time, pois:

  1. eu não tinha nenhum cronômetro disponível;
  2. cronometragem manual não é precisa;
  3. .NET faz magia negra para tornar o carregamento de aplicações mais rápida (quando uma aplicação é executada pela primeira vez, uma versão binária é gerada e armazenada no diretório Windows\assembly. Sim, é possível apagá-los, usando o comando gacutil /cdl, mas isso enche o saco :P).

[quote=Daniel Quirino Oliveira]Tirem suas conclusões.

(Ambiente de execução: Athlon XP 2800+, 512Mb Ram, Windows XP SP2)[/quote]

Conclusao: maquina bacana. Parabens. :mrgreen:

Achei interessante que a VM Server eh mais rapida no preenchimento dos dados porem mais lenta na ordenacao.

Qual a diferenca entre ambas?

Marcio Kuchma

[quote=kuchma]Achei interessante que a VM Server eh mais rapida no preenchimento dos dados porem mais lenta na ordenacao.

Qual a diferenca entre ambas?[/quote]

Tava aqui me perguntando a mesma coisa…

E se jogassemos o Pascalzão no combate??? Qual seria a situação?

Se eu tiver disposto de noite faço esse teste.

Chega de microbenchmarks, pelo amor de deus :evil:

Daqui a pouco vem alguem e diz “ah, mas eu faco isso rodar muuuuuuuuuito mais rapido usando C”. Aih outro vem e diz que nao, Java eh mais rapido. Ai vem outro com uma CFLAGS de meio quilometro. Ai vem outro com a mesma coisa em pascal. Ai vem outro com assembly. Ai vem outro com uma modelo pelada rebolando. Ai vem o Faustao, e depois o Gugu, e a gente acabou com a civilizacao e nem percebeu. PAREM.

Essa não deixa de ser uma má idéia. :smiley: Agora há daquele que deixar essa discussão cair nos ouvidos do Gugu ou do Faustão…

Falando sério, acho que estes testes são muito imparciais. Não dá pra avaliar a performance de uma linguagem apenas com um cálculo gingantesco dentro de um loop se reptindo várias vezes. As linguagens vão ter pontos onde sua performance será otimizada e outras em que haverá deficiências. Corrijam-me caso esteja errado, mas JAVA, por exemplo, por ter tipos primitivos, a priori, vai ser mais performatica nos cálculos do que uma linguagem completamente OO onde um integer vai ser um objeto, e por aí vai… esses testes são legais pra ficar brincando em casa, mas nada que vá te fazer escolher uma linguagem à outra…

Gustavo Guilherme BacK

[quote=back]
Essa não deixa de ser uma má idéia.


Falando sério, acho que estes testes são muito imparciais. [/quote]

:?: :?: :?: :?: :?: :?: :?: :?: :?:

tendi xongas :roll:

[]s

Back, linguagens nao tem performance, pq linguagens nao executam, rodam ou sao mensuraveis no espaco de tempo de nenhuma maneira interessante. Os interpretadores, sim :wink:

:oops: Ops! Verdade, mas quando se vai avaliar a performance, como nesse caso, quase sempre se vincula com a linguagem, mas como você disse não é isso que vai fazer diferença na execução de um teste. Fiz confusão…

Gustavo Guilherme BacK

[quote=caiofilipini][quote=kuchma]Achei interessante que a VM Server eh mais rapida no preenchimento dos dados porem mais lenta na ordenacao.

Qual a diferenca entre ambas?[/quote]

Tava aqui me perguntando a mesma coisa…[/quote]

A VM Server é mais rápida para preenchimento porque, se vocês repararem a forma como o array é preenchido (em um loop)é possível de se otimizar e fazer as demais bizarrices que o Hotspot faz para ganhar desempenho.
Agora, não faço a menor idéia do porquê ela é mais lenta para ordenação. Talvez ela tenha perdido tempo demais tentando otimizar antes de executar, coisa que a Client VM não faz (tanto assim).
Mas, basicamente (e a grosso modo), a Client VM é ajustada para oferecer um desempenho médio, mas com um leve consumo de memória, enquanto a Server VM vai procurar fazer de tudo o que for possivel para obter o melhor desempenho e gastar a memória que puder para isso. E é por isso que a Server VM perde no micro-benchmark-de-fundo-de-quintal-do-Daniel®, pois a aplicação não dura tempo o bastante para a VM conseguir recuperar, a longo prazo, o tempo que ela perdeu otimizando as “paradinhas”. O louds pode explicar estas coisas melhor do que eu. LOOOUUUUDSS!!

Mas, concordo com o CV. Estes mini-benchmarks de fundo de quintal (como o que eu fiz) não costumam provar nada. Mas foi um bom passa-tempo até eu conseguir pegar no sono :smiley:

Tá, desculpa minha ignorancia, mas como que executa a Server VM e como executar a Cliente VM:?:

Essa história de Server e Client VM são novas pra mim. Nunca tinha tomado conhecimento disso.

eita … execute só java pra ver as opcoes … tem -server e -client no meio delas.

Olá

Discordo completamente. Gostei muito do seu teste e foi muito elucidativo, dos melhores que já vi. Parabéns!

E ainda achei excelente o fato de você ter comparado usando também a opção -server. A JVM como padrão é otimizada para inicialização rápida e pouco gasto de memória. Com a opção -server se pode obter execuções mais rápidas as custas de um tempo maior na inicialização do sistema. E o que você falou está correto.

[]s
Luca

Luca, a parte fundo-de-quintal do teste do Daniel foi que a performance demonstrada ali nao reflete o que acontece de verdade em um sistema (ja que, em um sistema minimamente util, a VM tem que se preocupar com mais classes, IO, metodos maiores que nao sao tao hostpoteaveis assim, e por ai vai).

Mas foi legal pra demonstrar essas caracteristicas da VM Client e Server, e as diferencas entre as duas, nisso eu concordo com vc :slight_smile:

Concordo e também discordo.

Assembly não é linguagem de programação - OK

Eu acho que em aula de SW básico ninguém consegue montar um compilador, consegue??? Vai falar em Lex e Yacc no início… espanta todo mundo. Eu vi isso no quarto ano, nas aulas de Compiladores (lex e yacc pra não sacrificar e fazer tudo na mão)

Assembly não é produtivo = OK
Impossível implementar um simulador de um onibus espacial usando só assembly! [o nível de abstração é muito baixo]; Não concordo.

A NASA tem grana :$: e assim pode pagar qq programador que entenda bem de assembly pra fazer o que quiser, inclusive levitar. 8)

Pelo fato de ser baixissimo nivel tudo bem, mas que consegue consegue.

(não estou avaliando aqui se gasta tempo ou não)

Se construir em assembly fica confiável, não fica?

iv) Logo, a NASA usa várias tecnologias e desenvolve tecnologias também; == Penso logo existo

Legal esse assunto. Particularmente também não acho que seja utilizado só assembly lá, mas pq não né? Não podemos afirmar com tanta certeza sobre algo que não conhecemos.
:wink:

[]'s

[quote=cv]Luca, a parte fundo-de-quintal do teste do Daniel foi que a performance demonstrada ali nao reflete o que acontece de verdade em um sistema (ja que, em um sistema minimamente util, a VM tem que se preocupar com mais classes, IO, metodos maiores que nao sao tao hostpoteaveis assim, e por ai vai).

Mas foi legal pra demonstrar essas caracteristicas da VM Client e Server, e as diferencas entre as duas, nisso eu concordo com vc :)[/quote]

Exato. Eis um bom passatempo para benchmark “nem-tão-fundo-de-quintal-assim”: testes de performance de serialização de objetos, IO, Threading, método numéricos… Vamos nos tornar o próximo Gartner :smiley:

[quote=Daniel Quirino Oliveira]Não, não acho que seria vantajoso. Ok, poderia ser legal virar para o mundo e dizer “Hey, Java também serve para instalador de sistema operacional. Hip Hip Hurra!”. Mas, ponto final.

Primeiro, porque reescrever algo que já funciona muito bem sem adicionar novo valor ao produto é como jogar dinheiro pela janela (se quiser, pode jogar na janela de casa).

Segundo, porque scripts se encaixam muito bem neste tipo de aplicação de automatização de tarefas. E, acredite, se uma rotina bem escrita em Ruby já estiver razoavelmente grande, é possível que esta mesma rotina fique monstruosa em Java. Groovy talvez ficasse legal, mas aí é preciso ver se a nova versão vai adicionar algum valor à versão antiga.

Terceiro, deixa a galerinha dos scripts se divertirem com alguma coisa útil :smiley: huauhahuahua
[/quote]
Vamos esquecer a idéia de, por exemplo, reescrever o Portage, mas permita-me insistir mais um pouco no exemplo do instalador de pacotes. Já que você falou sobre o que poderia ser acrescentado, deixe-me contar uma “pequena” história.

Eu já tenho um certo tempo de uso de certas ferramentas para instalar pacotes (tipicamente, APT e Portage). Uma situação que eu vivo sempre e que, na qual, nenhuma destas ferramentas me deixa contente, é quando eu vou instalar vários pacotes de uma só vez.

O apt-get (APT) primeiramente faz o download de todos os pacotes para só depois começar a instalação. O emerge (Portage), diferentemente, baixa e instala um pacote por vez e só procede ao download do próximo pacote quando a instalação do pacote atual for concluída. Ambas as ferramentas, a meu ver, acabam levando um tempo excessivamente longo para instalar todos os pacotes, sendo que o Portage, além disso, acaba disperdiçando meu tempo de conexão com a Internet (o que, para um usuário de accesso discado à Internet como eu, é muito ruim).

Imaginemos agora que eu estou tentando instalar dois ou mais pacotes, sendo que um não dependa dos outros. O meu maior sonho é encontrar uma ferramenta para instalação de pacotes que me permita, neste caso, proceder ao download dos próximos pacotes enquanto faz a instalação do pacote atual. Sem dúvida, isto me economizaria tempo, tanto de instalação, quanto de conexão com a Internet.

Com algum esforço, eu consigo fazer isto hoje, mais ou menos, com o Portage. Na sua versão atual, o Portage utiliza arquivos de bloqueio para previnir que, por exemplo, duas execuções do emerge tentem fazer o download do mesmo arquivo ou desinstalar o mesmo pacote (até o presente momento, não há nada que as previna de tentar compilar o mesmo programa). Eu posso, por exemplo, abrir dois terminais e executar emerge --fetchonly <pacote1> <pacote2> …, no terminal 1, e emerge <pacote1> <pacote2> …, no terminal 2 (com o APT, isto não seria possível, mesmo porque ele não permite a execução do apt-get em múltiplos processos). Assim, o processo rodando no terminal 2 (instalação do pacote atual) vai aguardar pela liberação dos bloqueios criados pelo processo rodando no terminal 1 (download do pacote atual). Em suma, o processo no terminal 2 vai instalando os pacotes enquanto o processo no terminal 1 vai fazendo o download dos pacotes restantes.

Bom seria se eu pudesse fazer tudo isso sem precisar abrir vários terminais… Além disso, quem possui uma máquina mais potente pode querer compilar mais de um programa simultaneamente, usuários de banda larga podem querer fazer o download de vários pacotes simultaneamente (coisa que, altualmente, o Portage não permite), e por aí vai.

Pois bem. Eu imagino que uma ferramenta para instalação de pacotes poderia prover soluções para estes casos utilizando processamento concorrente (multi-threading). Então eu pergunto novamente: Isto seria possível? Viável? Vantajoso? E, se for vantajoso, seria mais vantajoso utilizando Java ou alguma outra linguagem que suporte multi-threading?

Desculpem-me se eu estiver falando bobagem, pois eu conheço muito pouco sobre processamento concorrente e sobre quais linguagens suportam-no atualmente.

Olá

Há uma restrição adicional que é a interdependência dos pacotes. Quando um pacotes depende de vários outros, o instalador precisaria ser inteligente o bastante para perceber isto e ir baixando e instalando na ordem certa. Não tenho a menor idéia sobre como esta informação poderia chegar ao instalador.

[]s
Luca