Eu tive o benefício de ler as outras respostas. Para começar pessoas como eu deveria saber a razão pela qual estamos lidando com um grande número inteiro tal aqui é que tanto Python
e bc
fazer direito associativo expansão exponenciação, o que significa que este não é 6^36
que estamos avaliando, mas sim 6^46656
que é consideravelmente maior. 1
Usando variações nos seguintes comandos, podemos extrair uma média para um elemento específico da saída da time
palavra e do comando reservados:
for i in {1..1000}; do (time echo 6^6^6 | bc > /dev/null) 2>&1; done | grep 'rea' | sed -e s/.*m// | awk '{sum += $1} END {print sum / NR}'
for i in {1..1000}; do (/usr/bin/time -v sh -c 'echo 6^6^6 | bc > /dev/null') 2>&1; done | grep 'Use' | sed -e s/.*:// | awk '{sum += $1} END {print sum / NR}'
É possível seguir outra rota e remover o arquivo inteiramente da comparação. Além disso, podemos comparar o tempo do bc com algo como o dc
comando, pois historicamente o primeiro é um "processador de front-end" para o segundo. Os seguintes comandos foram cronometrados:
echo 6^6^6 | bc
echo 6 6 6 ^ ^ p | dc
echo print 6**6**6 | python2.7
Observe que o dc
comando é associativo à esquerda para exponenciação. 2
Temos alguns resultados com time
(bash) para 1000 iterações (em segundos):
0.229678 real bc
0.228348 user bc
0.000569 sys bc
0.23306 real dc
0.231786 user dc
0.000395 sys dc
0.07 real python
0.065907 user python
0.003141 sys python
bc
e dc
oferecer desempenho comparável nesse contexto.
Resultados menos precisos 3, por exemplo, do comando /usr/bin/time
GNU time
(a precisão da escala não é válida aqui, mas os resultados são semelhantes):
0.2224 user bc
0 sys bc
0.23 Elapsed bc
0.22998 user dc
0 sys dc
0.23 Elapsed dc
0.06008 user python
0 sys python
0.07 Elapsed python
Uma vantagem /usr/bin/time
disso é que ele oferece a -v
opção que gera muito mais informações que podem ser úteis eventualmente.
Também é possível avaliar isso internamente, por assim dizer, com o timeit
módulo Python:
python2.7 -m timeit -n 1000 -r 1 'print 6**6**6' | grep 'loops'
1000 loops, best of 1: 55.4 msec per loop
Isso é um pouco mais rápido do que o que vimos antes. Vamos tentar o próprio intérprete:
>>> import timeit
>>> import sys
>>> import os
>>> T = timeit.Timer("print 6**6**6")
>>> n = int(1000)
>>> f = open(os.devnull, 'w')
>>> sys.stdout = f
>>> t = t.timeit(n)
>>> sys.stdout = sys.__stdout__
>>> print t/n
0.0553743481636
É o mais rápido que eu já vi.
Se avaliarmos uma exponenciação menor 6^6
, o comando time produzirá resultados surpreendentes - usando os mesmos for
comandos de loop que usamos, agora temos:
0.001001 bc real
0.000304 user
0.000554 sys
0.014 python real i.e. 10x more than bc??
0.010432 user
0.002606 sys
Então, com um número inteiro menor, bc
de repente é muito mais rápido? Da reinicialização do sistema à segunda execução, não faz diferença. No entanto, ao mesmo tempo, se usarmos timeit
para Python, obtemos:
python2.7 -m timeit -n 100000 -r 1 'print 6**6' | grep loops
100000 loops, best of 1: 0.468 usec per loop
Isso é microssegundos , não milissegundos, portanto, isso não corresponde aos resultados muito mais lentos usando o for
loop. Talvez outras ferramentas sejam necessárias para testar isso ainda mais e, como outros explicaram, há mais do que aparenta aqui. Parece que o Python foi mais rápido no cenário da pergunta, mas não está claro se é possível tirar conclusões além disso ...
1. Escusado será dizer que está além do escopo de algo como a expansão aritmética do eco, isto é echo $((6**6**6))
- bash
também é associativa correta para esse exemplo 6^6^6 = 6^(6^6)
.
2. Compare com esta: 6 6 ^ 6 ^ p
.
3. É possível que o comando GNU time forneça mais informações quando executado no BSD UNIX (documento de informações da hora GNU): A maioria das informações mostradas por 'time' é derivada da chamada de sistema 'wait3'. Os números são tão bons quanto os retornados por 'wait3'. Muitos sistemas não medem todos os recursos sobre os quais o 'tempo' pode ser reportado; esses recursos são relatados como zero. Os sistemas que medem a maioria ou todos os recursos são baseados em 4.2 ou 4.3BSD. Versões posteriores do BSD usam código de gerenciamento de memória diferente que mede menos recursos. - Nos sistemas que não possuem uma chamada 'wait3' que retorna informações de status, a chamada do sistema 'times' é usada. Ele fornece muito menos informações do que 'wait3'; portanto, o 'tempo' desses sistemas informa a maioria dos recursos como zero.