Performance das linguagens de Script na Web

A programação na web é geralmente conhecida pelas linguagens de scripting, como PHP, Perl, Ruby, ASP, Javascript, etc. Geralmente na sua execução recorre-se a interpretadores da linguagem o que deixa muito a desejar no que se refere a performance, ou seja, para se executar um programa é necessário chamar o programa que interpreta, ler o script, fazer o parsing do script e depois então executar as instruções. As instruções executadas não são as intruções nativas do processador, o atrasa o processo de execução.

Pelo contrário, as linguagens compiladas são bastante mais eficientes pois executam o código que anteriormente foi gerado na compilação, código este que são intruções nativas do processador. Assim, a execução é bem mais rápida pois o computador limita-se a executar o programa sem ter que se preocupar em determinar aquilo que tem que executar.

Para demonstrar esta diferença, executou-se um pequeno programa nas várias linguagens: C, Java, PHP, Perl, Python e Javascript. O programa
consiste em executar um ciclo de 0 a 99.999.999 e posteriormente medir o tempo de execução. Eis os vários programas e os respectivos tempos medidos:

Tempos (ms)Total (ms)Mínimo (ms)Máximo (ms)Média (ms)
C
#include <stdio.h>

int main() {
    int i;

    for(i=0;i<100000000;i++)
        if(i%1000000==0)
            printf("%d\n",i);
    return 0;
}
#1:984
#2:953
#3:938
#4:953
#5:953
#6:953
#7:953
#8:953
#9:954
#10:953
9547 938 984 954.700
Java
public class Benchmark {
    public static void main(String[] args) {
        int i;

        for(i=0;i<100000000;i++)
            if(i%1000000==0)
                System.out.println(i);
    }
}
#1:1125
#2:1078
#3:1047
#4:1109
#5:1078
#6:1063
#7:1062
#8:1063
#9:1046
#10:1063
10734 1046 1125 1073.400
PHP
<?php

for($i=0;$i<100000000;$i++)
    if($i%1000000==0)
        echo "$i\n";

?>
#1:11625
#2:11610
#3:11609
#4:11609
#5:11594
#6:11609
#7:11609
#8:11594
#9:11610
#10:11609
116078 11594 11625 11607.800
Python
for i in range(100000000):
    if i%1000000==0:
        print i
#1:20469
#2:20406
#3:20469
#4:20422
#5:20453
#6:20406
#7:20454
#8:20421
#9:20407
#10:20453
204360 20406 20469 20436.000
Perl
for($i=0;$i<100000000;$i++) {
    if ( $i%1000000 == 0 ) {
        print "$i\n";
    }
}

#1:23000
#2:23093
#3:22969
#4:22985
#5:22968
#6:22985
#7:22968
#8:22969
#9:22985
#10:22968
229890 22968 23093 22989.000

Para analizar o tempo de execução do Javascript teve-se que usar um método um pouco diferente. O Javascript geralmente é usado na programação de páginas Web, o que implica ser executado dentro de um browser. Usaram-se vários browsers para executar o programa de teste para analizar o comportamento em cada um deles, pois cada tem implementações diferentes.

Na tabela existem duas contagens, a Contagem Real a Contagem Desejada, que se deve ao facto dos browsers definirem um intervalo de execução. Quando o script demora mais tempo do que esse intervalo os browsers mostram uma mensagem dizendo que o script não está a responder, interrompendo-o. Como o tempo é medido usando o tempo real em milisegundos, o valor medido iria ser diferente daquele que realmente se esperaria medir. Assim, a Contagem Real é a iteração que realmente foi feita, e a Contagem Desejada é o valor que desejaria medir, que neste caso é 100000000, para assim se poder comparar os tempos de execução do teste anterior. O intervalo de excução varia de browser para browser, sendo que no Internet Explorer é de 1 segundos (o que faz com que o intervalo de execução seja menor do que nos restantes) e no Safari e no Mozilla Firefox é de 10 segundos.

Eis os resultados do teste:

 Tempos (ms)Contagem RealContagem DesejadaTotal Estimado (ms)Mínimo Estimado (ms)Máximo Estimado (ms)Média Estimada (ms)
Safari 4.0.5 (531.227) Windows #1:6538->32690
#2:6510->32550
#3:6500->32500
#4:6509->32545
#5:6559->32795
#6:6532->32660
#7:6540->32700
#8:6509->32545
#9:6536->32680
#10:8056->40280
20000000 100000000 333945 32500 40280 33394.5
Firefox 3.6.3 #1:7661->38305
#2:7660->38300
#3:7639->38195
#4:7583->37915
#5:7653->38265
#6:7731->38655
#7:7530->37650
#8:7541->37705
#9:7704->38520
#10:7533->37665
20000000 100000000 381175 37650 38655 38117.5
Internet Explorer 8.0.7600.16385 64-bits #1:422->42200
#2:422->42200
#3:406->40600
#4:437->43700
#5:421->42100
#6:406->40600
#7:422->42200
#8:422->42200
#9:422->42200
#10:422->42200
#11:437->43700
#12:438->43800
#13:407->40700
#14:407->40700
#15:421->42100
#16:407->40700
#17:438->43800
#18:407->40700
#19:406->40600
#20:422->42200
1000000100000000 839200 40600 43800 41960
Opera 10.53 Build: 3374 #1:12066->60330
#2:12104->60520
#3:12068->60340
#4:12080->60400
#5:12084->60420
#6:12049->60245
#7:12052->60260
#8:12142->60710
#9:12014->60070
#10:12236->61180
20000000 100000000 604475 60070 61180 60447.5

O testes realizado é um pouco simplista, na medida em que só analiza a capacidade de execução iterativa. Apesar disso, tem-se uma boa noção das performances de cada uma das linguagens.

Na tabela seguinte encontra-se o código fonte usado e uma pequena descrição acerca do ambiente de execução:

Código fonte
Programa para a contagem do tempo C Java PHP Python Perl Javascript
Código CódigoComando CódigoComando CódigoComando CódigoComando CódigoComando CódigoComando
Ambiente de Execução
Mainboardclevo M7X0SU
ChipsetSiS 671/FX/DX/MX
ProcessorIntel Pentium Dual CPU T3400 @ 2.16GHz
Physical Memory4096 MB (2 x 2048 DDR2-SDRAM )
Video CardNVIDIA GeForce 9300M GS
Operating SystemWindows 7 Ultimate Professional 6.01.7600 (x64)