Estou avaliando a expressão 6^6^6
usando python
e bc
separadamente.
O conteúdo do arquivo python é print 6**6**6
. Quando executo time python test.py
, recebo a saída como
real 0m0.067s
user 0m0.050s
sys 0m0.011s
E então, eu executei o comando time echo 6^6^6 | bc
que me deu a seguinte saída
real 0m0.205s
user 0m0.197s
sys 0m0.005s
A partir desses resultados, fica claro que o tempo de sys gasto por python e bc foi de 11 ms e 5 ms, respectivamente. O comando bc superou o python em nível de tempo do sistema, mas quando se trata de usuário e em tempo real, o python foi quase quatro vezes mais rápido que o bc . O que poderia ter acontecido lá. Eu não dei nenhuma prioridade aos processos como tais. Eu estou tentando entender essa situação.
python
performance
process-management
bc
ganessh
fonte
fonte
echo | bc
envolve o lançamento de um subshell por causa do canal - é daí que provavelmente parte do seu tempo extra de usuário. Para fazer deste um teste equitativo, o script python deve ler em stdin para que você possatime echo 6**6**6 | whatever.py
.echo 6^6^6 | time bc
.6**6**6
expressão é realmente calculada em tempo de compilação . No entanto, como você está iniciando o arquivo diretamente em vez de importá-lo de um módulo, isso não deve importar. Para ver a diferença colocada10**12345678
em uma.py
arquivo e tentar importá-lo do intérprete interativo. Depois feche o intérprete, reinicie-o e importea
novamente. A primeira vez que deve ter uma quantidade considerável de tempo (porque pitão está a compilar o módulo), enquanto que a segunda vez que ele carrega o.pyc
, que deve ser instantânea,Respostas:
Python importa um grande número de arquivos na inicialização:
Cada uma delas requer um número ainda maior de tentativas para abrir um arquivo Python, porque existem várias maneiras de definir um módulo:
Cada "tentativa", exceto as incorporadas, requer chamadas de sistema operacional / sistema, e cada "importação" parece acionar cerca de 8 mensagens de "tentativa". (Havia maneiras de reduzir isso usando zipimport, e cada caminho no seu PYTHONPATH pode exigir outra chamada.)
Isso significa que existem quase 200 chamadas de sistema stat antes que o Python inicie na minha máquina, e "time" atribui isso a "sys" em vez de "user", porque o programa do usuário aguarda o sistema para fazer as coisas.
Por comparação, e como Terdon disse, "bc" não tem um custo inicial tão alto. Observando a saída dtruss (eu tenho um Mac; "strace" para um sistema operacional baseado em Linux), vejo que o bc não faz nenhuma chamada de sistema aberta () ou stat (), exceto por carregar algumas compartilhadas bibliotecas são o começo, o que obviamente o Python também. Além disso, o Python tem mais arquivos para ler, antes de estar pronto para processar qualquer coisa.
A espera do disco está lenta.
Você pode ter uma noção do custo de inicialização do Python fazendo:
São 0,032s na minha máquina, enquanto 'print 6 ** 6 ** 6' é 0,072s; portanto, o custo de inicialização é de 1/2 do tempo total e o cálculo + conversão para decimal é a outra metade. Enquanto:
leva 0,005s e "6 ^ 6 ^ 6" leva 0,184s, de modo que a exponenciação de bc é 4x mais lenta que a de Python, embora seja 7x mais rápido para começar.
fonte
Encontrei uma boa resposta para explicar os diferentes campos:
Portanto, no seu exemplo específico, a versão python é mais rápida em termos do tempo real que leva para ser concluído. No entanto, a abordagem python gasta mais tempo no espaço do kernel, fazendo chamadas para funções do kernel. O
bc
comando gasta essencialmente pouco tempo no espaço do kernel e todo o seu tempo é gasto no espaço do usuário, presumivelmente executando obc
código interno .Isso não faz diferença para você, a única informação com a qual você realmente se importa é
real
qual é o tempo real decorrido entre iniciar o comando e obter sua saída.Você também deve estar ciente de que essas pequenas diferenças não são estáveis, elas também dependerão da carga do seu sistema e serão alteradas toda vez que você executar o comando:
fonte
Vou explicar de outra perspectiva.
Para ser justo,
bc
tem vantagem, pois não precisa ler nada do disco e precisa apenas de seus blob / binários, enquanto o python precisa importar uma série de módulos + lendo um arquivo. Portanto, seu teste pode ser tendenciosobc
. Para testá-lo, você deve usarbc -q file
wherefile
contém:Mudando exatamente isso modificou o tempo de uso
echo
:Para usar o arquivo:
(você precisará usar o método de terdon para perceber diferenças maiores, mas pelo menos sabemos que são)
Agora, da perspectiva do python, o python precisa ler do disco, compilar e executar cada vez que o arquivo, além de carregar módulos como aponta Andrew , o que torna o tempo de execução mais lento. Se você compilar o código de bytes do script python, notará que leva 50% menos tempo total para executar o código:
compilado:
Como você pode ver, existem vários fatores que podem afetar a execução do tempo entre diferentes ferramentas.
fonte
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
ebc
fazer direito associativo expansão exponenciação, o que significa que este não é6^36
que estamos avaliando, mas sim6^46656
que é consideravelmente maior. 1Usando 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:É 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:Observe que o
dc
comando é associativo à esquerda para exponenciação. 2Temos alguns resultados com
time
(bash) para 1000 iterações (em segundos):bc
edc
oferecer desempenho comparável nesse contexto.Resultados menos precisos 3, por exemplo, do comando
/usr/bin/time
GNUtime
(a precisão da escala não é válida aqui, mas os resultados são semelhantes):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:Isso é um pouco mais rápido do que o que vimos antes. Vamos tentar o próprio intérprete:
É o mais rápido que eu já vi.
Se avaliarmos uma exponenciação menor
6^6
, o comando time produzirá resultados surpreendentes - usando os mesmosfor
comandos de loop que usamos, agora temos: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 usarmostimeit
para Python, obtemos: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 exemplo6^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.
fonte