Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Performance Python: Como construir métodos e funções fast and furious?

Performance Python: Como construir métodos e funções fast and furious?

Já fez uma função/método que travou sua máquina ao ser executada!? Pois é ... Eu já!

Nesta palestra demonstrarei:
- Alternativas para que você não trave nada na sua máquina por falta de memória ou cpu;
- Como você poderá distinguir uma função Fuscão preto de uma função Brasília amarela.

More Decks by Rafael Henrique da Silva Correia

Other Decks in Technology

Transcript

  1. Eu Rafael Henrique da Silva Correia @rafaelhenrique http://blog.abraseucodigo.com.br - Desenvolvedor

    Python na Olist (temos vagas!) - Aprendiz de Golang - Rogue em World of Warcraft - Não gosto de Java!
  2. Performance? Gastar menos e fazer mais! • Menos uso de

    CPU e conseguir terminar suas tarefas • Menos uso de memória RAM e conseguir terminar suas tarefas • Menos uso de I/O de disco e conseguir terminar suas tarefas Ou seja, o mais importante é terminar suas tarefas em um tempo aceitável! :-)
  3. Que comece a corrida... ## Qual código é mais veloz

    (e furioso)? # Primeiro exemplo grupys_infinitos = [] for edicao in range(0,10000): grupys_infinitos.append(f'Grupy-SP {edicao}') # Segundo exemplo grupys_infinitos = [f'Grupy-SP {edicao}' for edicao in range(0,10000)]
  4. Use o timeit! [1] >>> import timeit >>> meu_codigo_1 =

    """ grupys_infinitos = [] for edicao in range(0,10000): grupys_infinitos.append(f'Grupy-SP {edicao}') """ >>> timeit.timeit(meu_codigo_1, number=10000) 20.100100330018904 Ref. https://docs.python.org/3/library/timeit.html
  5. Use o timeit! [2] >>> import timeit >>> meu_codigo_2 =

    """ grupys_infinitos = [f'Grupy-SP {edicao}' for edicao in range(0,10000)] """ >>> timeit.timeit(meu_codigo_2, number=10000) 13.710857237980235 >>> # Este é mais veloz (e furioso!) Ref. https://docs.python.org/3/library/timeit.html
  6. Use o timeit! [3] $ python3 -m timeit '"-".join(str(n) for

    n in range(100))' 10000 loops, best of 5: 30.2 usec per loop $ python3 -m timeit '"-".join([str(n) for n in range(100)])' 10000 loops, best of 5: 27.5 usec per loop $ python3 -m timeit '"-".join(map(str, range(100)))' 10000 loops, best of 5: 23.2 usec per loop Ref. https://docs.python.org/3/library/timeit.html
  7. Criamos um código Dominic Toretto? Para este problema sim! :-)

    Motivos: • O código é veloz? … Sim é! • Consigo completar sua execução? … Sim consigo! • O tempo de processamento é muito alto? … Não é! • O consumo de memória é muito alto? … Presumo que não :-/
  8. Como medir o consumo de memória? [1] Ref. https://stackoverflow.com/questions/14372006/variables-memory-size-in-python #

    O que consome mais uma tupla ou uma lista? >>> from sys import getsizeof >>> tupla = tuple(f'Grupy-SP {edicao}' for edicao in range(0,10000)) >>> getsizeof(tupla) 80048 >>> lista = list(f'Grupy-SP {edicao}' for edicao in range(0,10000)) >>> getsizeof(lista) 83112
  9. Como medir o consumo de memória? [2] pip install memory_profiler

    Ref. https://pypi.org/project/memory_profiler/
  10. Como medir o consumo de memória? [2] from memory_profiler import

    profile @profile def multiplica_letra(): a = 'a' * 10000000 b = 'b' * 10000001 del b return a if __name__ == '__main__': multiplica_letra() Ref. https://pypi.org/project/memory_profiler/
  11. Como medir o consumo de memória? [2] Filename: teste05.py Line

    # Mem usage Increment Line Contents ================================================ 3 13.2 MiB 13.2 MiB @profile 4 def multiplica_letra(): 5 22.8 MiB 9.5 MiB a = 'a' * 10000000 6 32.1 MiB 9.3 MiB b = 'b' * 10000001 7 22.8 MiB -9.3 MiB del b 8 22.8 MiB 0.0 MiB return a Ref. https://pypi.org/project/memory_profiler/
  12. Como medir o consumo de memória? [3] from memory_profiler import

    profile @profile def grupys_infinitos_01(): grupys_infinitos = [] for edicao in range(0, 10000): grupys_infinitos.append(f'Grupy-SP {edicao}') return grupys_infinitos if __name__ == '__main__': grupys_infinitos_01() Ref. https://pypi.org/project/memory_profiler/
  13. Como medir o consumo de memória? [3] Filename: teste06.py Line

    # Mem usage Increment Line Contents ================================================ 4 13.3 MiB 13.3 MiB @profile 5 def grupys_infinitos_01(): 6 13.3 MiB 0.0 MiB grupys_infinitos = [] 7 13.9 MiB 0.7 MiB for edicao in range(0, 10000): 8 13.9 MiB 0.0 MiB grupys_infinitos.append... 9 13.9 MiB 0.0 MiB return grupys_infinitos Ref. https://pypi.org/project/memory_profiler/
  14. Como medir o consumo de memória? [4] from memory_profiler import

    profile @profile def grupys_infinitos_02(): return [f'Grupy-SP {edicao}' for edicao in range(0, 10000)] if __name__ == '__main__': grupys_infinitos_02() Ref. https://pypi.org/project/memory_profiler/
  15. Como medir o consumo de memória? [4] Filename: teste07.py Line

    # Mem usage Increment Line Contents ================================================ 12 13.1 MiB 13.1 MiB @profile 13 def grupys_infinitos_02(): 14 13.8 MiB 0.7 MiB return [f'Grupy-SP {edicao}' ... Ref. https://pypi.org/project/memory_profiler/
  16. Como medir o consumo de CPU? [1] Ref. https://docs.python.org/3/library/profile.html import

    cProfile import io import pstats pr = cProfile.Profile() pr.enable() [your code here] pr.disable() stream = io.StringIO() ps = pstats.Stats(pr, stream=stream).sort_stats('cumulative') ps.print_stats(10) print(stream.getvalue())
  17. Como medir o consumo de CPU? [1] [your code begin...]

    import time def brasilia(): time.sleep(10) def fusca(): time.sleep(9) brasilia() fusca() [your code end...] Ref. https://docs.python.org/3/library/profile.html
  18. Como medir o consumo de CPU? [1] 5 function calls

    in 19.005 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 2 19.005 9.503 19.005 9.503 {built-in method time.sleep} 1 0.000 0.000 10.005 10.005 teste08.py:6(brasilia) 1 0.000 0.000 9.001 9.001 teste08.py:10(fusca) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} Ref. https://docs.python.org/3/library/profile.html
  19. Como medir o consumo de CPU? [2] pip install pytest-benchmark

    Ref. https://pypi.org/project/pytest-benchmark/
  20. Como medir o consumo de CPU? [2] def soma(x, y):

    return x + y def teste_soma(benchmark): # realiza benchmark da função de soma result = benchmark(soma, 10, 20) # verifica se a soma deu o resultado esperado assert result == 30 Ref. https://pypi.org/project/pytest-benchmark/
  21. Como medir o consumo de CPU? [2] $ # Executando

    o código $ pytest --benchmark-columns=min,max,mean teste09.py … linhas omitidas … -------------- benchmark: 1 tests --------------1/1) Name (time in ns) Min Max Mean ------------------------------------------------ teste_soma 84.2402 441.6500 88.0371 ------------------------------------------------ … linhas omitidas … Ref. https://pypi.org/project/pytest-benchmark/
  22. Como medir o consumo de CPU? [2] def somatorio(numeros): resultado

    = 0 for numero in numeros: resultado += numero return resultado def teste_somatorio(benchmark): # realiza benchmark da função de somatorio result = benchmark(somatorio, [10, 20]) # verifica se a somatorio deu o resultado esperado assert result == 30 Ref. https://pypi.org/project/pytest-benchmark/
  23. Como medir o consumo de CPU? [2] def teste_sum(benchmark): #

    realiza benchmark da função de sum result = benchmark(sum, [10, 20]) # verifica se a sum deu o resultado esperado assert result == 30 Ref. https://pypi.org/project/pytest-benchmark/
  24. Como medir o consumo de CPU? [2] $ # Executando

    o código $ pytest --benchmark-columns=min,max,mean teste10.py … linhas omitidas … ------------------------------- benchmark: 2 tests Name (time in ns) Min Max Mean -------------------------------------------------------------------------------- teste_sum 83.8301 (1.0) 668.2900 (1.0) 87.8679 (1.0) teste_somatorio 172.8968 (2.06) 1,607.2761 (2.41) 189.3247 (2.15) -------------------------------------------------------------------------------- … linhas omitidas … Ref. https://pypi.org/project/pytest-benchmark/
  25. Dica final Antes de procurar soluções mirabolantes procure na standard

    library (built-in) do próprio Python! Just Python! :-) Aqui nesta palestra temos exemplos que isso funciona muito bem (built-in): • import timeit • from sys import getsizeof • import cProfile Mas vale lembrar que coisas extras trazem facilidades: • pip install memory_profiler • pip install pytest-benchmark
  26. Referências Códigos contidos nos slides: https://gist.github.com/rafaelhenrique/f18bbfafd3c9066f3eca3f1f024937ed Trabalhe conosco: https://www.99jobs.com/olist Code

    Highlighter https://github.com/romannurik/SlidesCodeHighlighter Módulo timeit https://docs.python.org/3/library/timeit.html Otimização de memória RAM https://stackoverflow.com/questions/14372006/variables-memory-size-in-python https://pypi.org/project/memory_profiler/ Otimização de CPU https://docs.python.org/3/library/profile.html https://pypi.org/project/pytest-benchmark/