User Tools

Site Tools


perl:parrot_vs_outras_linguagens

Perl vs Outras Linguagens

Antes de mais gostaria de salientar que o objectivo deste pequeno estudo não é provar quais as linguagens que devem ou não ser utilizadas, nem provar quais as linguagens mais rápidas ou mais lentas. Cada equipa de desenvolvimento deve ser capaz de avaliar os pontos positivos e negativos de cada linguagem, de modo a escolher a linguagem (ou linguagens) onde é capaz de tirar mais proveito das vantagens que essa linguage oferece, e reduzir ao máximo o impacto das desvantagens introduzidas pela escolha dessa mesma linguagem.

As Linguagens

A linguagem que estamos interessados em estudar neste caso é o Perl, que é categorizado como uma linguagem dinâmica. As características típicas desta família de linguagens são responsáveis por uma conhecida degradação de performance e escalabilidade das soluções implementadas. Assim optamos por um conjunto de linguagens dinâmicas bastante utilizadas que representam uma grande fatia da escolha para implementação de soluções no mercado. Usamos também algumas linguagens com características menos dinâmicas de modo a ter uma base de comparação. Utilizamos ainda o Parrot para ter uma ideia de como esta linguagem, ainda em fase de desenvolvimento, se virá a comportar no futuro.

  • dinâmicas
    • Perl
    • PHP
    • Python
    • Ruby
  • estáticas
    • C
    • Java
  • difíceis de catalogar
    • Parrot

Benchmarks Efectuados

Os benchmarks efectuados foram bastante simples. A ideia por trás de cada de um deles é a seguinte:

  1. escolher um problema típico;
  2. desenvolver um algoritmo capaz de resolver este problema usando uma técnica ou paradigma de programação bastante conhecida;
  3. implementar este algortimo nas várias de linguagens, tentanto manter as implementações o mais análogas possíveis e tentando evitar atalhos específicos de cada linguagem;
  4. correr cada implementação diversas vezes e registar a variação do tempo de execução;
  5. comparar resultados.

Todos os benchmarks foram efectuados no mesmo contexto: o mesmo sistema operativo, no mesmo estado, na mesma máquina.

Caso de Estudo 1 - iteração simples

O Problema

A iteração simples é uma técnica bastante utilizada na programação. Para ilustrar esta técnica criamos um algoritmo que calcula quantos números primos existem entre 1 e um dado argumento. O algoritmo não tem qualquer tipo de optimização, limita-se a fazer uma série de iterações para efectuar o cálculo. Basicamente foram apenas utilizados whiles e ifs. Corremos cada implementação várias vezes fazendo variar o argumento entre 10_000 e 90_000, com saltos de 10_000.

function is_prime(n) {
  for $i (1..n) {
    if $i % $n == 0
      return 0
  }
  return 1
}

for $i (1..argumento) {
  if is_prime($i)
    $resultado++
}

Os Resultados

C Java Parrot Perl PHP Python Ruby
10_000 0.32 0.94 3.20 5.49 7.92 8.42 18.46
20_000 1.15 1.48 9.99 20.14 22.79 29.60 66.16
30_000 2.47 2.74 21.30 42.92 48.95 63.81 142.32
40_000 4.27 4.69 36.73 75.10 84.70 110.35 246.29
50_000 6.54 6.89 55.93 114.49 129.30 169.75 376.23
60_000 9.27 9.79 79.24 173.20 183.49 239.81 538.06
70_000 12.34 12.94 105.43 214.33 244.36 319.44 711.12
80_000 16.00 16.64 136.36 280.16 316.30 413.67 921.38
90_000 19.99 20.69 170.44 347.09 395.59 516.79 1168.45

Caso de Estudo 2 - IO

Para testar IO devemos limitar a parte computacional a um mínimo. Nesse sentido sugiro a impressão de números de 1 a 1_000_000_000 ou mais. Dados problemas de tamanho de tipos de dados, podemos fazer de forma diferente:

Depois de alguns testes, 2000/2000 já dá um ficheiro de 34 megas.

  for $a (1..1_000_000) {
     for $b (1..1_000_000) {
        print "$a $b\n";
     }
  }

Isto pode ser testado de duas formas. Tal como está (redireccionar), ou com um open/print/close. Do meu ponto de vista, acho que devemos usar as duas abordagens.

Implementações

Falta adaptar para receber um parametro :-/

C

Para redireccionar

 #include <stdio.h>
 int main() {
    int a, b;
    for (a=1; a <= 1000000; ++a)
       for (b=1; b <= 1000000; ++b)
          printf("%d %d\n", a, b);
    return 0;
 }

Escrevendo directamente em ficheiro

 #include <stdio.h>
 int main() {
    int a, b;
    FILE *f;
    f = fopen("out", "w+");
    for (a=1; a <= 1000000; ++a)
       for (b=1; b <= 1000000; ++b)
          fprintf(f,"%d %d\n", a, b);
    fclose(f);
    return 0;
 }
Perl

Para redireccionar

 for $a (1..1_000_000)
    for $b (1..1_000_000)
       print "$a $b\n";

Escrevendo directamente em ficheiro

 open F, ">out";
 for $a (1..1_000_000)
    for $b (1..1_000_000)
       print F "$a $b\n";
 close F;
Ruby

Para redireccionar

   1000000.times {
     |a|
     1000000.times {
       |b|
       print "#{a} #{b} \n"
     };
   };

Criando ficheiros

   file = File.open("out", mode_string = "w+");
   2000.times {
     |a|
     2000.times {
       |b|
       file.print("#{a} #{b}\n")
     };
   };
   file.close;

Os Resultados

TODO

Caso de Estudo 3 - manipulação de strings

Para a manipulação de strings tenho alguns problemas. Não podemos usar simplesmente regexps, senão estamos lixados a implementar em C. Também era giro um exercício que, além de obrigar a fazer substrings, também fizesse as strings crescer (reallocs em C).

Um possível problema é a sequência: 1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, 31131211131221, 13211311123113112211, …

Os Resultados

TODO

Caso de Estudo 4 - recursividade

A recursividade é uma técnica bastante utilizada para resolver de uma maneira rápida bastante problemas, mas deve ser usada com cuidado porque pode facilmente introduzir um grande overhead de computação desnecessário para a resolução do problema em si. A recursividade, mais uma vez, não deve usar muita memória, nem IO. Os valores passados por parâmetro também devem ser minimais. Assim optámos por implementar um algoritmo bastante simples que calcula o número de nodos de uma árvore binária recebendo como argumento a altura da árvore. Assim temos operações bastante simples delegando para a recursividade a responsabilidade de maior parte da computação.

function nodes_number(height) {
    if (height == 0) 
        return 1
    else 
        return 1 + nodes_number(height-1) + (nodes_number(height-1)
}

Os Resultados

TODO

Nuno Carvalho: 2008/07/10 14:21

perl/parrot_vs_outras_linguagens.txt · Last modified: 2008/08/07 12:21 by ambs