O Project Euler e outros concursos de codificação geralmente têm um tempo máximo para execução ou as pessoas se gabam da rapidez com que sua solução específica é executada. Com o Python, às vezes as abordagens são um pouco esquisitas - ou seja, adicionando código de temporização ao __main__
.
Qual é uma boa maneira de criar um perfil de quanto tempo um programa Python leva para executar?
python
performance
profiling
time-complexity
Chris Lawlor
fonte
fonte
Respostas:
Python inclui um criador de perfil chamado cProfile . Ele não apenas fornece o tempo total de execução, mas também cronometra cada função separadamente e informa quantas vezes cada função foi chamada, facilitando a determinação de onde você deve fazer otimizações.
Você pode chamá-lo de dentro do seu código ou do intérprete, assim:
Ainda mais útil, você pode chamar o cProfile ao executar um script:
Para tornar ainda mais fácil, criei um pequeno arquivo em lote chamado 'profile.bat':
Então, tudo o que tenho a fazer é executar:
E eu entendo isso:
EDIT: Link atualizado para um bom recurso de vídeo do PyCon 2013 intitulado Python Profiling
Also via YouTube .
fonte
python -m cProfile -o <out.profile> <script>
), RunSnakeRun , chamado comorunsnake <out.profile>
inestimável.cprofile
ainda é recomendado maisprofile
.Há um tempo atrás eu fiz o
pycallgraph
que gera uma visualização do seu código Python. Edit: Eu atualizei o exemplo para trabalhar com o 3.3, a versão mais recente deste artigo.Após a
pip install pycallgraph
instalação do GraphViz, você pode executá-lo na linha de comando:Ou você pode criar um perfil de partes específicas do seu código:
Qualquer um desses itens gerará um
pycallgraph.png
arquivo semelhante à imagem abaixo:fonte
Traceback (most recent call last): /pycallgraph.py", line 90, in generate output.done() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 94, in done source = self.generate() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 143, in generate indent_join.join(self.generate_attributes()), File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 169, in generate_attributes section, self.attrs_from_dict(attrs), ValueError: zero length field name in format
sudo apt-get install graphviz
.Vale ressaltar que o uso do criador de perfil só funciona (por padrão) no thread principal e você não obterá nenhuma informação de outros threads se usá-los. Isso pode ser um pouco complicado, pois não é mencionado na documentação do criador de perfil .
Se você também deseja criar um perfil de threads, consulte a
threading.setprofile()
função nos documentos.Você também pode criar sua própria
threading.Thread
subclasse para fazer isso:e use essa
ProfiledThread
classe em vez da classe padrão. Pode oferecer mais flexibilidade, mas não tenho certeza se vale a pena, especialmente se você estiver usando código de terceiros que não usaria sua classe.fonte
target
função do Thread , que é o que athreading.Thread.run()
chamada executa. Mas, como eu disse na resposta, provavelmente não vale a pena subclassificar o Thread, pois qualquer código de terceiros não o utilizará e, em vez disso, o utilizaráthreading.setprofile()
.O wiki do python é uma ótima página para recursos de criação de perfil: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
assim como os documentos python: http://docs.python.org/library/profile.html
como mostrado por Chris Lawlor cProfile é uma ótima ferramenta e pode ser facilmente usada para imprimir na tela:
ou arquivar:
PS> Se você estiver usando o Ubuntu, instale o python-profile
Se você imprimir em arquivo, poderá obter boas visualizações usando as seguintes ferramentas
PyCallGraph: uma ferramenta para criar imagens de gráficos de chamadas
:
corre:
Visão:
Você pode usar o que quiser para ver o arquivo png, usei o gimp
Infelizmente, eu sempre
ponto: o gráfico é muito grande para os bitmaps do cairo-renderer. Dimensionamento de 0,257079 para ajustar
o que torna minhas imagens inutilmente pequenas. Então, geralmente crio arquivos svg:
PS> certifique-se de instalar o graphviz (que fornece o programa de pontos):
Gráfico alternativo usando gprof2dot via @maxy / @quodlibetor:
fonte
O comentário de Maxy sobre essa resposta me ajudou o suficiente para que eu mereça a sua própria resposta: eu já tinha arquivos .pstats gerados pelo cProfile e não queria executar novamente as coisas com o pycallgraph, então usei o gprof2dot e fiquei bonita svgs:
e BLAM!
Ele usa ponto (a mesma coisa que o pycallgraph usa) para que a saída seja semelhante. Tenho a impressão de que o gprof2dot perde menos informações:
fonte
pwd
/gprof2dot/gprof2dot.py $ HOME / bin (ou use ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin na maioria dos shells - o sotaque grave é usado como formatação no primeiro versão).ln
errado a ordem dos argumentos quase sempre.Encontrei uma ferramenta útil chamada SnakeViz ao pesquisar este tópico. O SnakeViz é uma ferramenta de visualização de perfis baseada na Web. É muito fácil de instalar e usar. A maneira usual de usá-lo é gerar um arquivo stat
%prun
e depois fazer a análise no SnakeViz.A principal técnica de visualização usada é o gráfico Sunburst, como mostrado abaixo, no qual a hierarquia das chamadas de função é organizada como camadas de arcos e informações de tempo codificadas em suas larguras angulares.
A melhor coisa é que você pode interagir com o gráfico. Por exemplo, para ampliar, é possível clicar em um arco, e o arco e seus descendentes serão ampliados como um novo raio de sol para exibir mais detalhes.
fonte
A maneira mais simples e rápida de descobrir para onde está indo o tempo todo.
Desenha um gráfico de pizza em um navegador. A maior peça é a função do problema. Muito simples.
fonte
Eu acho que isso
cProfile
é ótimo para criação de perfil, enquantokcachegrind
é ótimo para visualizar os resultados. Opyprof2calltree
meio lida com a conversão do arquivo.Para instalar as ferramentas necessárias (no Ubuntu, pelo menos):
O resultado:
fonte
brew install qcachegrind
e substitude cadakcachegrind
comqcachegrind
a descrição de perfis de sucesso.export QT_X11_NO_MITSHM=1
Também vale mencionar o visualizador de despejo de GUI cProfile RunSnakeRun . Ele permite que você ordene e selecione, ampliando assim as partes relevantes do programa. O tamanho dos retângulos na imagem é proporcional ao tempo gasto. Se você passar o mouse sobre um retângulo, destacará as chamadas na tabela e em todos os lugares do mapa. Quando você clica duas vezes em um retângulo, ele aumenta o zoom nessa parte. Ele mostrará quem chama essa parte e o que essa parte chama.
A informação descritiva é muito útil. Ele mostra o código desse bit que pode ser útil quando você está lidando com chamadas de biblioteca internas. Ele informa qual arquivo e qual linha encontrar o código.
Também quero destacar que o OP disse 'criação de perfil', mas parece que ele quis dizer 'tempo'. Lembre-se de que os programas serão mais lentos quando analisados.
fonte
Um bom módulo de criação de perfil é o line_profiler (chamado usando o script kernprof.py). Pode ser baixado aqui .
Meu entendimento é que o cProfile fornece apenas informações sobre o tempo total gasto em cada função. Portanto, linhas de código individuais não são cronometradas. Esse é um problema na computação científica, pois muitas vezes uma única linha pode levar muito tempo. Além disso, como me lembro, o cProfile não pegou o tempo que eu estava gastando em digitar numpy.dot.
fonte
Recentemente, criei atum para visualizar perfis de tempo de execução e importação do Python; isso pode ser útil aqui.
Instale com
Crie um perfil de tempo de execução
ou um perfil de importação (é necessário o Python 3.7+)
Em seguida, basta executar o atum no arquivo
fonte
pprofile
line_profiler
(já apresentado aqui) também inspiradopprofile
, descrito como:Ele fornece granularidade de linha, pois
line_profiler
é um Python puro, pode ser usado como um comando ou módulo independente e pode até gerar arquivos no formato de chamada de grupo que podem ser facilmente analisados[k|q]cachegrind
.vprof
Há também o vprof , um pacote Python descrito como:
fonte
Há muitas ótimas respostas, mas elas usam a linha de comando ou algum programa externo para criar um perfil e / ou classificar os resultados.
Eu realmente senti falta de alguma maneira que eu poderia usar no meu IDE (eclipse-PyDev) sem tocar na linha de comando ou instalar nada. Então aqui está.
Criação de perfil sem linha de comando
Consulte documentos ou outras respostas para obter mais informações.
fonte
Seguindo a resposta de Joe Shaw sobre o código multiencadeado para não funcionar conforme o esperado,
runcall
concluí que o método no cProfile está apenas executandoself.enable()
eself.disable()
chama a chamada de função com perfil, para que você possa fazer isso sozinho e ter o código que desejar entre eles. interferência mínima com o código existente.fonte
cprofile.py
código-fonte do revela que é exatamenteruncall()
isso que faz. Para ser mais específico, depois de criar uma instância de Perfil comprof = cprofile.Profile()
, chame imediatamenteprof.disable()
e adicioneprof.enable()
eprof.disable()
chame a seção de código que você deseja criar.Na fonte de Virtaal, há uma classe e um decorador muito úteis que podem facilitar muito a criação de perfis (mesmo para métodos / funções específicos). A saída pode ser visualizada com muito conforto no KCacheGrind.
fonte
O cProfile é ótimo para criação de perfil rápido, mas na maioria das vezes era finalizado para mim com os erros. A função runctx resolve esse problema inicializando corretamente o ambiente e as variáveis, espero que possa ser útil para alguém:
fonte
Se você deseja criar um criador de perfil cumulativo, ou seja, executar a função várias vezes seguidas e observar a soma dos resultados.
você pode usar este
cumulative_profiler
decorador:é python> = 3.6 específico, mas você pode remover
nonlocal
para que funcione em versões mais antigas.Exemplo
perfilando a função
baz
baz
correu 5 vezes e imprimiu isto:especificando a quantidade de vezes
fonte
A solução apenas para terminal (e mais simples), no caso de todas essas UI sofisticadas falharem na instalação ou na execução:
ignore
cProfile
completamente e substitua-a porpyinstrument
, que coletará e exibirá a árvore de chamadas logo após a execução.Instalar:
Perfil e resultado da exibição:
Funciona com python2 e 3.
[EDIT] A documentação da API, para criação de perfil apenas uma parte do código, pode ser encontrada aqui .
fonte
Meu jeito é usar o yappi ( https://github.com/sumerc/yappi ). É especialmente útil combinado com um servidor RPC onde (mesmo apenas para depuração) você registra o método para iniciar, parar e imprimir informações de criação de perfil, por exemplo:
Em seguida, quando o programa funcionar, você poderá iniciar o criador de perfil a qualquer momento chamando o
startProfiler
método RPC e despejar informações de criação de perfil em um arquivo de log chamandoprintProfiler
(ou modifique o método rpc para devolvê-lo ao chamador) e obter essa saída:Pode não ser muito útil para scripts curtos, mas ajuda a otimizar processos do tipo servidor, especialmente porque o
printProfiler
método pode ser chamado várias vezes ao longo do tempo para criar um perfil e comparar, por exemplo, diferentes cenários de uso do programa.Nas versões mais recentes do yappi, o seguinte código funcionará:
fonte
def printProfiler(): if not yappi_available: return stats = yappi.get_func_stats() stats.print_all(columns={0:("name",90), 1:("ncall", 5), 2:("tsub", 8), 3:("ttot", 8), 4:("tavg",8)})
(OK, depois de algumas vezes inserir o bloco de código no comentário que desisti. isso é incrivelmente difícil para um site de perguntas e respostas orientado à programação. )Uma nova ferramenta para lidar com criação de perfil em Python é o PyVmMonitor: http://www.pyvmmonitor.com/
Possui alguns recursos exclusivos, como
Nota: é comercial, mas gratuito para código aberto.
fonte
gprof2dot_magic
Função mágica para
gprof2dot
criar o perfil de qualquer instrução Python como um gráfico DOT no JupyterLab ou no Jupyter Notebook.Repo GitHub: https://github.com/mattijn/gprof2dot_magic
instalação
Verifique se você tem o pacote Python
gprof2dot_magic
.Suas dependências
gprof2dot
egraphviz
serão instaladas tambémuso
Para ativar a função mágica, primeiro carregue o
gprof2dot_magic
móduloe então perfil qualquer declaração de linha como um gráfico DOT como tal:
fonte
https://github.com/amoffat/Inspect-Shell
Você poderia usar isso (e seu relógio de pulso).
fonte
Para adicionar a https://stackoverflow.com/a/582337/1070617 ,
Eu escrevi este módulo que permite usar o cProfile e visualizar sua saída facilmente. Mais aqui: https://github.com/ymichael/cprofilev
Consulte também: http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html sobre como entender as estatísticas coletadas.
fonte
Isso dependeria do que você deseja ver na criação de perfil. Métricas simples de tempo podem ser fornecidas por (bash).
Mesmo '/ usr / bin / time' pode gerar métricas detalhadas usando o sinalizador '--verbose'.
Para verificar as métricas de tempo fornecidas por cada função e entender melhor quanto tempo é gasto nas funções, você pode usar o cProfile embutido em python.
Entrando em métricas mais detalhadas, como desempenho, o tempo não é a única métrica. Você pode se preocupar com memória, threads, etc.
Opções de criação de perfil:
1. line_profiler é outro gerador de perfil usado normalmente para descobrir métricas de tempo linha por linha.
2. memory_profiler é uma ferramenta para analisar o uso de memória.
3. heapy (do projeto Guppy) Crie um perfil de como os objetos na pilha são usados.
Estes são alguns dos mais comuns que costumo usar. Mas se você quiser descobrir mais, tente ler este livro. É um livro muito bom sobre como começar com o desempenho em mente. Você pode passar para tópicos avançados sobre o uso de python compilado Cython e JIT (Just-in-time).
fonte
Com um criador de perfil estatístico como austin , nenhuma instrumentação é necessária, o que significa que você pode obter dados de criação de perfil de um aplicativo Python simplesmente com
A saída bruta não é muito útil, mas você pode canalizar isso para o flamegraph.pl para obter uma representação gráfica dos dados que fornece uma descrição de onde o tempo (medido em microssegundos de tempo real) está sendo gasto.
fonte
Para obter estatísticas rápidas do perfil em um notebook IPython. Pode-se incorporar line_profiler e memory_profiler em linha reta em seus notebooks.
Outro pacote útil é o Pympler . É um poderoso pacote de criação de perfil capaz de rastrear classes, objetos, funções, vazamentos de memória etc. Exemplos abaixo, documentos anexados.
Pegue!
Carregue-o!
Use-o!
%Tempo
Dá:
% timeit
% de poda
Dá:
% memit
Dá:
% lprun
Dá:
sys.getsizeof
Retorna o tamanho de um objeto em bytes.
asizeof () do pympler
pympler.asizeof pode ser usado para investigar quanta memória determinados objetos Python consomem. Em contraste com sys.getsizeof, um tamanho de objetos recursivamente
rastreador do pympler
Rastreia a vida útil de uma função.
O pacote Pympler consiste em um grande número de funções de alta utilidade para codificar o perfil. Tudo isso não pode ser coberto aqui. Consulte a documentação anexada para implementações de perfil detalhado.
Pympler doc
fonte
Há também um perfilador estatístico chamado
statprof
. É um criador de perfil de amostragem, por isso adiciona uma sobrecarga mínima ao seu código e fornece tempos baseados em linhas (não apenas baseados em funções). É mais adequado para aplicativos em tempo real, como jogos, mas pode ter menos precisão que o cProfile.A versão no pypi é um pouco antiga, portanto, é possível instalá-la
pip
especificando o repositório git :Você pode executá-lo assim:
Consulte também https://stackoverflow.com/a/10333592/320036
fonte
Acabei de desenvolver meu próprio criador de perfil inspirado em pypref_time:
https://github.com/modaresimr/auto_profiler
Ao adicionar um decorador, ele mostrará uma árvore de funções demoradas
@Profiler(depth=4, on_disable=show)
Exemplo
Saída de exemplo
fonte
Quando não sou root no servidor, uso lsprofcalltree.py e executo meu programa da seguinte maneira:
Então, posso abrir o relatório com qualquer software compatível com callgrind , como qcachegrind
fonte