etc./StackOverFlow

Python 스크립트를 어떻게 프로파일링할 수 있습니까?

청렴결백한 만능 재주꾼 2022. 3. 7. 11:53
반응형

질문자 :Chris Lawlor


Project Euler 및 기타 코딩 대회는 종종 최대 실행 시간이 있거나 사람들이 특정 솔루션이 실행되는 속도를 자랑합니다. Python을 사용하면 때때로 접근 방식이 다소 복잡합니다. 즉, __main__ 타이밍 코드를 추가하는 것입니다.

Python 프로그램을 실행하는 데 걸리는 시간을 프로파일링하는 좋은 방법은 무엇입니까?



Python에는 cProfile 이라는 프로파일러가 포함되어 있습니다. 총 실행 시간을 제공할 뿐만 아니라 각 함수를 개별적으로 곱하고 각 함수가 호출된 횟수를 알려주므로 어디에서 최적화를 수행해야 하는지 쉽게 결정할 수 있습니다.

다음과 같이 코드 내에서 또는 인터프리터에서 호출할 수 있습니다.

 import cProfile cProfile.run('foo()')

훨씬 더 유용하게는 스크립트를 실행할 때 cProfile을 호출할 수 있습니다.

 python -m cProfile myscript.py

더 쉽게 만들기 위해 'profile.bat'라는 작은 배치 파일을 만들었습니다.

 python -m cProfile %1

그래서 내가해야 할 일은 실행하는 것입니다.

 profile euler048.py

그리고 나는 이것을 얻는다 :

 1007 function calls in 0.061 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.061 0.061 <string>:1(<module>) 1000 0.051 0.000 0.051 0.000 euler048.py:2(<lambda>) 1 0.005 0.005 0.061 0.061 euler048.py:2(<module>) 1 0.000 0.000 0.061 0.061 {execfile} 1 0.002 0.002 0.053 0.053 {map} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler objects} 1 0.000 0.000 0.000 0.000 {range} 1 0.003 0.003 0.003 0.003 {sum}

편집: Python Profiling 이라는 제목의 PyCon 2013에서 좋은 비디오 리소스에 대한 링크를 업데이트했습니다.
또한 YouTube를 통해 .


Chris Lawlor

얼마 전에 파이썬 코드에서 시각화를 생성하는 pycallgraph 편집: 이 글을 쓰는 시점에서 최신 릴리스인 3.3에서 작동하도록 예제를 업데이트했습니다.

pip install pycallgraphGraphViz 설치 후 명령줄에서 실행할 수 있습니다.

 pycallgraph graphviz -- ./mypythonscript.py

또는 코드의 특정 부분을 프로파일링할 수 있습니다.

 from pycallgraph import PyCallGraph from pycallgraph.output import GraphvizOutput with PyCallGraph(output=GraphvizOutput()): code_to_profile()

둘 중 하나는 아래 이미지와 유사한 pycallgraph.png

여기에 이미지 설명 입력


gak

프로파일러를 사용하는 것은 기본 스레드에서만 작동하며(기본적으로) 다른 스레드를 사용하는 경우 다른 스레드로부터 정보를 얻지 못한다는 점을 지적할 가치가 있습니다. 이것은 프로파일러 문서 에서 완전히 언급되지 않았기 때문에 약간의 문제가 될 수 있습니다.

스레드도 프로파일링하려면 문서에서 threading.setprofile() 함수 를 살펴보고 싶을 것입니다.

자신만의 threading.Thread 서브클래스를 생성하여 이를 수행할 수도 있습니다.

 class ProfiledThread(threading.Thread): # Overrides threading.Thread.run() def run(self): profiler = cProfile.Profile() try: return profiler.runcall(threading.Thread.run, self) finally: profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

표준 클래스 대신 ProfiledThread 클래스를 사용합니다. 더 많은 유연성을 제공할 수 있지만 그만한 가치가 있는지 확실하지 않습니다. 특히 클래스를 사용하지 않는 타사 코드를 사용하는 경우에는 더욱 그렇습니다.


Joe Shaw

파이썬 위키는 프로파일링 리소스를 위한 훌륭한 페이지입니다: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

파이썬 문서와 같습니다: http://docs.python.org/library/profile.html

Chris Lawlor가 표시한 것처럼 cProfile은 훌륭한 도구이며 화면에 인쇄하는 데 쉽게 사용할 수 있습니다.

 python -m cProfile -s time mine.py <args>

또는 파일:

 python -m cProfile -o output.file mine.py <args>

PS> Ubuntu를 사용하는 경우 python-profile을 설치해야 합니다.

 apt-get install python-profiler

파일로 출력하면 다음 도구를 사용하여 멋진 시각화를 얻을 수 있습니다.

PyCallGraph : 호출 그래프 이미지를 생성하는 도구
설치:

 pip install pycallgraph

운영:

 pycallgraph mine.py args

보다:

 gimp pycallgraph.png

png 파일을 보려면 원하는 것을 사용할 수 있습니다. 저는 gimp를 사용했습니다.
불행히도 나는 종종

점: 그래프가 cairo-renderer 비트맵에 대해 너무 큽니다. 0.257079에 맞게 크기 조정

내 이미지를 사용할 수 없을 정도로 작게 만듭니다. 그래서 나는 일반적으로 svg 파일을 만듭니다.

 pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS> graphviz(도트 프로그램 제공)를 설치해야 합니다.

 pip install graphviz

@maxy / @quodlibetor를 통해 gprof2dot을 사용하는 대체 그래프:

 pip install gprof2dot python -m cProfile -o profile.pstats mine.py gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

brent.payne

이 답변에 대한 @Maxy의 의견은 자체 답변을 받을 자격이 있다고 생각하기에 충분히 도움이 되었습니다. 이미 cProfile에서 생성된 .pstats 파일이 있고 pycallgraph로 작업을 다시 실행하고 싶지 않았기 때문에 gprof2dot 를 사용했고 예뻐졌습니다 . svgs:

 $ sudo apt-get install graphviz $ git clone https://github.com/jrfonseca/gprof2dot $ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin $ cd $PROJECT_DIR $ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

그리고 블램!

점(pycallgraph가 사용하는 것과 동일한 것)을 사용하므로 출력이 비슷해 보입니다. 나는 gprof2dot이 더 적은 정보를 잃는다는 인상을 받았습니다.

gprof2dot 예제 출력


quodlibetor

항상 어디로 가고 있는지 찾는 가장 간단 하고 빠른 방법입니다.

 1. pip install snakeviz 2. python -m cProfile -o temp.dat <PROGRAM>.py 3. snakeviz temp.dat

브라우저에서 원형 차트를 그립니다. 가장 큰 부분은 문제 기능입니다. 매우 간단합니다.


CodeCabbie

이 주제를 조사할 때 SnakeViz 라는 편리한 도구를 만났습니다. SnakeViz는 웹 기반 프로파일링 시각화 도구입니다. 설치 및 사용이 매우 쉽습니다. 내가 사용하는 일반적인 방법은 %prun 으로 통계 파일을 생성한 다음 SnakeViz에서 분석하는 것입니다.

사용된 주요 비주얼리제이션 기술은 아래와 같이 Sunburst 차트 이며, 여기서 함수 호출의 계층은 각 너비로 인코딩된 호 및 시간 정보의 레이어로 배열됩니다.

가장 좋은 점은 차트와 상호 작용할 수 있다는 것입니다. 예를 들어 확대하려면 호를 클릭하면 호와 그 하위 항목이 새로운 햇살로 확대되어 자세한 내용을 표시할 수 있습니다.

여기에 이미지 설명 입력


zaxliu

cProfile 은 프로파일링에 적합하고 kcachegrind 는 결과 시각화에 적합합니다. 그 pyprof2calltree 는 파일 변환을 처리합니다.

 python -m cProfile -o script.profile script.py pyprof2calltree -i script.profile -o script.calltree kcachegrind script.calltree

필수 시스템 패키지:

  • kcachegrind (리눅스), qcachegrind (맥OS)

우분투에서 설정:

 apt-get install kcachegrind pip install pyprof2calltree

결과:

결과 스크린샷


Federico

최근에 Python 런타임 및 가져오기 프로필을 시각화하기 위해 참치를 만들었습니다. 이것은 여기에서 도움이 될 수 있습니다.

여기에 이미지 설명 입력

다음으로 설치

 pip install tuna

런타임 프로필 만들기

 python3 -m cProfile -o program.prof yourfile.py

또는 가져오기 프로필(Python 3.7 이상 필요)

 python3 -X importprofile yourfile.py 2> import.log

그런 다음 파일에서 참치를 실행하십시오.

 tuna program.prof

Nico Schlömer

또한 언급할 가치가 있는 것은 GUI cProfile 덤프 뷰어 RunSnakeRun 입니다. 이를 통해 프로그램의 관련 부분을 확대하여 정렬하고 선택할 수 있습니다. 사진에서 사각형의 크기는 걸린 시간에 비례합니다. 직사각형 위에 마우스를 가져가면 테이블과 지도의 모든 곳에서 해당 호출이 강조 표시됩니다. 사각형을 더블 클릭하면 해당 부분이 확대됩니다. 누가 그 부분을 부르고 그 부분이 무엇을 부르는지 보여줍니다.

설명 정보는 매우 도움이 됩니다. 내장 라이브러리 호출을 처리할 때 도움이 될 수 있는 해당 비트에 대한 코드를 보여줍니다. 코드를 찾을 파일과 줄을 알려줍니다.

또한 OP가 '프로파일링'이라고 말했지만 '타이밍'을 의미한 것으로 보입니다. 프로파일링할 때 프로그램이 느리게 실행된다는 점에 유의하십시오.

여기에 이미지 설명 입력


Pete

프로필

line_profiler (이미 여기에 표시됨)는 다음과 같이 설명되는 pprofile

라인 세분성, 스레드 인식 결정론적 및 통계적 순수 Python 프로파일러

line_profiler 로 라인 세분성을 제공하고 [k|q]cachegrind 로 쉽게 분석할 수 있는 callgrind 형식 파일을 생성할 수도 있습니다.

vprof

다음과 같이 설명된 Python 패키지 vprof 도 있습니다.

[...] 실행 시간 및 메모리 사용량과 같은 다양한 Python 프로그램 특성에 대한 풍부한 대화형 시각화를 제공합니다.

히트맵


BenC

좋은 프로파일링 모듈은 line_profiler입니다(kernprof.py 스크립트를 사용하여 호출됨). 여기에서 다운로드할 수 있습니다.

내 이해는 cProfile이 각 기능에 소요된 총 시간에 대한 정보만 제공한다는 것입니다. 따라서 개별 코드 줄에는 시간이 지정되지 않습니다. 종종 한 줄에 많은 시간이 소요될 수 있기 때문에 이것은 과학 컴퓨팅에서 문제입니다. 또한 내가 기억하는 것처럼 cProfile은 내가 numpy.dot에서 보내는 시간을 포착하지 못했습니다.


Ian Langmore

훌륭한 답변이 많이 있지만 결과를 프로파일링 및/또는 정렬하기 위해 명령줄이나 외부 프로그램을 사용합니다.

명령줄을 건드리거나 아무 것도 설치하지 않고 IDE(eclipse-PyDev)에서 사용할 수 있는 방법을 정말 놓쳤습니다. 여기 있습니다.

명령줄 없이 프로파일링

 def count(): from math import sqrt for x in range(10**5): sqrt(x) if __name__ == '__main__': import cProfile, pstats cProfile.run("count()", "{}.profile".format(__file__)) s = pstats.Stats("{}.profile".format(__file__)) s.strip_dirs() s.sort_stats("time").print_stats(10)

자세한 내용은 문서 또는 기타 답변을 참조하세요.


David Mašek

모든 멋진 UI가 설치되거나 실행되지 않는 경우를 대비하여 터미널 전용(그리고 가장 간단한) 솔루션:
cProfile 완전히 무시하고 실행 직후 호출 트리를 수집하고 표시하는 pyinstrument 대체합니다.

설치:

 $ pip install pyinstrument

프로필 및 표시 결과:

 $ python -m pyinstrument ./prog.py

python2 및 3에서 작동합니다.

[편집] 코드의 일부만 프로파일링하기 위한 API 문서는여기 에서 찾을 수 있습니다.


Francois

멀티 스레드 코드가 예상대로 작동하지 않는다는 Joe Shaw의 답변에 따라 cProfile runcall self.enable()self.disable() 호출을 수행하는 것일 뿐이므로 간단히 수행할 수 있습니다. 기존 코드와의 간섭을 최소화하면서 원하는 모든 코드를 사용할 수 있습니다.


PypeBros

Virtaal의 소스 에는 프로파일링(특정 메소드/함수에 대해서도)을 매우 쉽게 만들 수 있는 매우 유용한 클래스와 데코레이터가 있습니다. 그러면 KCacheGrind에서 출력을 매우 편안하게 볼 수 있습니다.


Walter

함수를 연속으로 여러 번 실행하고 결과의 합계를 보는 것을 의미하는 누적 프로파일러를 만들고 싶다면.

cumulative_profiler 데코레이터를 사용할 수 있습니다.

python >= 3.6에 해당하지만 이전 버전에서 작동 nonlocal

 import cProfile, pstats class _ProfileFunc: def __init__(self, func, sort_stats_by): self.func = func self.profile_runs = [] self.sort_stats_by = sort_stats_by def __call__(self, *args, **kwargs): pr = cProfile.Profile() pr.enable() # this is the profiling section retval = self.func(*args, **kwargs) pr.disable() self.profile_runs.append(pr) ps = pstats.Stats(*self.profile_runs).sort_stats(self.sort_stats_by) return retval, ps def cumulative_profiler(amount_of_times, sort_stats_by='time'): def real_decorator(function): def wrapper(*args, **kwargs): nonlocal function, amount_of_times, sort_stats_by # for python 2.x remove this row profiled_func = _ProfileFunc(function, sort_stats_by) for i in range(amount_of_times): retval, ps = profiled_func(*args, **kwargs) ps.print_stats() return retval # returns the results of the function return wrapper if callable(amount_of_times): # incase you don't want to specify the amount of times func = amount_of_times # amount_of_times is the function in here amount_of_times = 5 # the default amount return real_decorator(func) return real_decorator

예시

baz 프로파일링

 import time @cumulative_profiler def baz(): time.sleep(1) time.sleep(2) return 1 baz()

baz 를 5번 실행하고 다음을 인쇄했습니다.

 20 function calls in 15.003 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 10 15.003 1.500 15.003 1.500 {built-in method time.sleep} 5 0.000 0.000 15.003 3.001 <ipython-input-9-c89afe010372>:3(baz) 5 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}

횟수 지정

 @cumulative_profiler(3) def baz(): ...

moshevi

cProfile은 빠른 프로파일링에 적합하지만 대부분의 경우 오류로 끝났습니다. 함수 runctx는 환경과 변수를 올바르게 초기화하여 이 문제를 해결합니다. 누군가에게 유용할 수 있기를 바랍니다.

 import cProfile cProfile.runctx('foo()', None, locals())

Datageek

내 방법은 yappi( https://github.com/sumerc/yappi )를 사용하는 것입니다. (디버깅을 위해서라도) 프로파일링 정보를 시작, 중지 및 인쇄하는 방법을 등록하는 RPC 서버와 결합하면 특히 유용합니다. 예를 들면 다음과 같습니다.

 @staticmethod def startProfiler(): yappi.start() @staticmethod def stopProfiler(): yappi.stop() @staticmethod def printProfiler(): stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20) statPrint = '\n' namesArr = [len(str(stat[0])) for stat in stats.func_stats] log.debug("namesArr %s", str(namesArr)) maxNameLen = max(namesArr) log.debug("maxNameLen: %s", maxNameLen) for stat in stats.func_stats: nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))] log.debug('nameAppendSpaces: %s', nameAppendSpaces) blankSpace = '' for space in nameAppendSpaces: blankSpace += space log.debug("adding spaces: %s", len(nameAppendSpaces)) statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str( round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n" log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub") log.log(1000, statPrint)

startProfiler RPC 메서드를 호출하여 언제든지 프로파일러를 시작 printProfiler 를 호출하여(또는 호출자에게 반환하도록 rpc 메서드를 수정하여) 프로파일링 정보를 로그 파일에 덤프하고 다음과 같은 출력을 얻을 수 있습니다.

 2014-02-19 16:32:24,128-|SVR-MAIN |-(Thread-3 )-Level 1000: name ncall ttot tsub 2014-02-19 16:32:24,128-|SVR-MAIN |-(Thread-3 )-Level 1000: C:\Python27\lib\sched.py.run:80 22 0.11 0.05 M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293 22 0.11 0.0 M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515 22 0.11 0.0 M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66 1 0.0 0.0 C:\Python27\lib\BaseHTTPServer.py.date_time_string:464 1 0.0 0.0 c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243 4 0.0 0.0 C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537 1 0.0 0.0 c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4 0.0 0.0 <string>.__new__:8 220 0.0 0.0 C:\Python27\lib\socket.py.close:276 4 0.0 0.0 C:\Python27\lib\threading.py.__init__:558 1 0.0 0.0 <string>.__new__:8 4 0.0 0.0 C:\Python27\lib\threading.py.notify:372 1 0.0 0.0 C:\Python27\lib\rfc822.py.getheader:285 4 0.0 0.0 C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301 1 0.0 0.0 C:\Python27\lib\xmlrpclib.py.end:816 3 0.0 0.0 C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467 1 0.0 0.0 C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460 1 0.0 0.0 C:\Python27\lib\SocketServer.py.close_request:475 1 0.0 0.0 c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066 4 0.0 0.0

printProfiler 메서드가 시간이 지남에 따라 여러 번 호출되어 다른 프로그램 사용 시나리오를 프로파일링하고 비교할 수 있는 경우 서버 유형 프로세스를 최적화하는 데 도움이 됩니다.

최신 버전의 yappi에서는 다음 코드가 작동합니다.

 @staticmethod def printProfile(): yappi.get_func_stats().print_all()

Mr. Girgitt

IPython 노트북에서 빠른 프로필 통계를 얻으려면. line_profilermemory_profiler 를 노트북에 직접 포함할 수 있습니다.

또 다른 유용한 패키지는 Pympler 입니다. 클래스, 객체, 함수, 메모리 누수 등을 추적할 수 있는 강력한 프로파일링 패키지입니다. 아래 예제, 문서 첨부.

받아!

 !pip install line_profiler !pip install memory_profiler !pip install pympler

로드!

 %load_ext line_profiler %load_ext memory_profiler

사용해!


%시각

 %time print('Outputs CPU time,Wall Clock time') #CPU times: user 2 µs, sys: 0 ns, total: 2 µs Wall time: 5.96 µs

제공:

  • CPU 시간: CPU 수준 실행 시간
  • sys 시간: 시스템 수준 실행 시간
  • 총계: CPU 시간 + 시스템 시간
  • 벽 시간: 벽시계 시간

%시간

 %timeit -r 7 -n 1000 print('Outputs execution time of the snippet') #1000 loops, best of 7: 7.46 ns per loop
  • 루핑(n)회에서 주어진 실행 횟수(r) 중 가장 좋은 시간을 제공합니다.
  • 시스템 캐싱에 대한 세부 정보를 출력합니다.
    • 코드 조각이 여러 번 실행되면 시스템은 몇 가지 작업을 캐시하고 프로필 보고서의 정확성을 저해할 수 있는 작업을 다시 실행하지 않습니다.

%정리

 %prun -s cumulative 'Code to profile'

제공:

  • 함수 호출 수(ncalls)
  • 함수 호출당 항목이 있음(고유)
  • 호출당 소요 시간(percall)
  • 해당 함수 호출까지 경과된 시간(cumtime)
  • etc...라는 함수/모듈의 이름

누적 프로필


%미트

 %memit 'Code to profile' #peak memory: 199.45 MiB, increment: 0.00 MiB

제공:

  • 메모리 사용량

%lprun

 #Example function def fun(): for i in range(10): print(i) #Usage: %lprun <name_of_the_function> function %lprun -f fun fun()

제공:

  • 라인 와이즈 통계

라인 프로필


sys.getsizeof

 sys.getsizeof('code to profile') # 64 bytes

객체의 크기를 바이트 단위로 반환합니다.


pympler의 asizeof()

 from pympler import asizeof obj = [1,2,("hey","ha"),3] print(asizeof.asizeof(obj,stats=4))

pympler.asizeof는 특정 Python 객체가 소비하는 메모리 양을 조사하는 데 사용할 수 있습니다. sys.getsizeof와 달리 asizeof는 재귀적으로 객체의 크기를 조정합니다.

pympler.asizeof


pympler의 추적기

 from pympler import tracker tr = tracker.SummaryTracker() def fun(): li = [1,2,3] di = {"ha":"haha","duh":"Umm"} fun() tr.print_diff()

함수의 수명을 추적합니다.

추적기 출력

Pympler 패키지는 코드를 프로파일링하기 위한 수많은 높은 유틸리티 기능으로 구성됩니다. 여기에서 모두 다룰 수는 없습니다. 자세한 프로필 구현에 대해서는 첨부된 문서를 참조하십시오.

핌플러 문서


Aditya Patnaik

gprof2dot_magic

JupyterLab 또는 Jupyter Notebook에서 모든 Python 문을 DOT 그래프로 프로파일링하는 gprof2dot 용 매직 기능.

여기에 이미지 설명 입력

GitHub 저장소: https://github.com/mattijn/gprof2dot_magic

설치

gprof2dot_magic 이 있는지 확인하십시오.

 pip install gprof2dot_magic

종속성 gprof2dotgraphviz 도 설치됩니다.

용법

매직 기능을 활성화하려면 먼저 gprof2dot_magic 모듈을 로드하십시오.

 %load_ext gprof2dot_magic

그런 다음 라인 문을 다음과 같이 DOT 그래프로 프로파일링합니다.

 %gprof2dot print('hello world')

여기에 이미지 설명 입력


Mattijn

austin 과 같은 통계 프로파일러를 사용하면 계측이 필요하지 않습니다. 즉, 다음을 사용하여 Python 애플리케이션에서 프로파일링 데이터를 얻을 수 있습니다.

 austin python3 my_script.py

원시 출력은 그다지 유용하지 않지만 이를 Flamegraph.pl 에 파이프하여 시간(실시간의 마이크로초로 측정)이 소비되는 위치에 대한 분석을 제공하는 해당 데이터의 플레임 그래프 표현을 얻을 수 있습니다.

 austin python3 my_script.py | flamegraph.pl > my_script_profile.svg

또는 웹 애플리케이션 Speedscope.app 을 사용하여 수집된 샘플을 빠르게 시각화할 수도 있습니다. pprof가 설치되어 있으면 austin-python (예: pipx install austin-python 사용)을 austin2pprof 를 사용하여 pprof 형식으로 변환할 수도 있습니다.


Phoenix87

최근에 PyCharm 편집기에서 line_profiler 의 결과를 쉽게 분석하고 시각화할 수 있는 PyCharm용 플러그인을 만들었습니다.

line_profiler 는 다른 답변에서도 언급되었으며 특정 줄에서 파이썬 인터프리터가 소비한 시간을 정확히 분석하는 훌륭한 도구입니다.

내가 만든 PyCharm 플러그인은 https://plugins.jetbrains.com/plugin/16536-line-profiler에서 찾을 수 있습니다.

Python 환경에서 pip 또는 플러그인 자체로 설치할 수 있는 line-profiler-pycharm 이라는 도우미 패키지가 필요합니다.

PyCharm에 플러그인을 설치한 후:

  1. line_profiler_pycharm.profile 데코레이터로 프로파일링하려는 기능을 데코레이션하십시오.
  2. '프로필 라인' 러너로 실행

결과 스크린샷: 라인 프로파일러 Pycharm 결과


jusx

https://stackoverflow.com/a/582337/1070617 에 추가하려면,

나는 당신이 cProfile을 사용하고 그 출력을 쉽게 볼 수 있도록 하는 이 모듈을 작성했습니다. 추가 정보: https://github.com/ymichael/cprofilev

 $ python -m cprofilev /your/python/program # Go to http://localhost:4000 to view collected statistics.

수집된 통계를 이해하는 방법에 대해서는 http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html 도 참조하십시오.


michael

Python에서 프로파일링을 처리하는 새로운 도구는 PyVmMonitor입니다. http://www.pyvmmonitor.com/

다음과 같은 독특한 기능이 있습니다.

  • 실행 중인(CPython) 프로그램에 프로파일러 연결
  • Yappi 통합을 통한 주문형 프로파일링
  • 다른 컴퓨터의 프로필
  • 다중 프로세스 지원(멀티프로세싱, django...)
  • 라이브 샘플링/CPU 보기(시간 범위 선택 포함)
  • cProfile/profile 통합을 통한 결정적 프로파일링
  • 기존 PStats 결과 분석
  • DOT 파일 열기
  • 프로그래밍 방식 API 액세스
  • 방법 또는 라인별로 샘플 그룹화
  • 파이 개발 통합
  • 파이참 통합

참고: 상업적이지만 오픈 소스에서는 무료입니다.


Fabio Zadrozny

프로파일링에서 무엇을 보고자 하는지에 따라 다릅니다. 간단한 시간 메트릭은 (bash)로 제공할 수 있습니다.

 time python python_prog.py

'/usr/bin/time'에서도 '--verbose' 플래그를 사용하여 자세한 메트릭을 출력할 수 있습니다.

각 함수에서 제공하는 시간 메트릭을 확인하고 함수에 소요된 시간을 더 잘 이해하기 위해 파이썬에서 내장 cProfile을 사용할 수 있습니다.

성능과 같은 더 자세한 메트릭으로 이동하면 시간이 유일한 메트릭이 아닙니다. 메모리, 스레드 등에 대해 걱정할 수 있습니다.
프로파일링 옵션:
1. line_profiler 는 라인 단위로 타이밍 메트릭을 찾는 데 일반적으로 사용되는 또 다른 프로파일러입니다.
2. memory_profiler 는 메모리 사용량을 프로파일링하는 도구입니다.
3. heapy(프로젝트 Guppy에서) 힙의 개체가 사용되는 방법을 프로파일링합니다.

이것들은 내가 자주 사용하는 일반적인 것들 중 일부입니다. 그러나 더 자세히 알고 싶다면 이 책을 읽어보십시오. 성능을 염두에 두고 시작하는 것에 대한 꽤 좋은 책입니다. Cython 및 JIT(Just-in-time) 컴파일된 Python 사용에 대한 고급 항목으로 이동할 수 있습니다.


user7891524

방금 pypref_time에서 영감을 받은 나만의 프로파일러를 개발했습니다.

https://github.com/modaresimr/auto_profiler

데코레이터를 추가하면 시간이 많이 걸리는 함수 트리가 표시됩니다.

@Profiler(depth=4, on_disable=show)

 Install by: pip install auto_profiler

예시

 import time # line number 1 import random from auto_profiler import Profiler, Tree def f1(): mysleep(.6+random.random()) def mysleep(t): time.sleep(t) def fact(i): f1() if(i==1): return 1 return i*fact(i-1) def show(p): print('Time [Hits * PerHit] Function name [Called from] [Function Location]\n'+\ '-----------------------------------------------------------------------') print(Tree(p.root, threshold=0.5)) @Profiler(depth=4, on_disable=show) def main(): for i in range(5): f1() fact(3) if __name__ == '__main__': main()

예제 출력

 Time [Hits * PerHit] Function name [Called from] [function location] ----------------------------------------------------------------------- 8.974s [1 * 8.974] main [auto-profiler/profiler.py:267] [/test/t2.py:30] ├── 5.954s [5 * 1.191] f1 [/test/t2.py:34] [/test/t2.py:14] │ └── 5.954s [5 * 1.191] mysleep [/test/t2.py:15] [/test/t2.py:17] │ └── 5.954s [5 * 1.191] <time.sleep> | | | # The rest is for the example recursive function call fact └── 3.020s [1 * 3.020] fact [/test/t2.py:36] [/test/t2.py:20] ├── 0.849s [1 * 0.849] f1 [/test/t2.py:21] [/test/t2.py:14] │ └── 0.849s [1 * 0.849] mysleep [/test/t2.py:15] [/test/t2.py:17] │ └── 0.849s [1 * 0.849] <time.sleep> └── 2.171s [1 * 2.171] fact [/test/t2.py:24] [/test/t2.py:20] ├── 1.552s [1 * 1.552] f1 [/test/t2.py:21] [/test/t2.py:14] │ └── 1.552s [1 * 1.552] mysleep [/test/t2.py:15] [/test/t2.py:17] └── 0.619s [1 * 0.619] fact [/test/t2.py:24] [/test/t2.py:20] └── 0.619s [1 * 0.619] f1 [/test/t2.py:21] [/test/t2.py:14]

Ali

그 파이썬 스크립트가 무엇을 하는지 알고 싶으십니까? 검사 셸을 입력합니다. Inspect Shell을 사용하면 실행 중인 스크립트를 중단하지 않고 전역을 인쇄/변경하고 기능을 실행할 수 있습니다. 이제 자동 완성 및 명령 기록이 있습니다(Linux에만 해당).

Inspect Shell은 pdb 스타일 디버거가 아닙니다.

https://github.com/amoffat/Inspect-Shell

당신은 그것을 사용할 수 있습니다 (그리고 당신의 손목 시계).


Colonel Panic

statprof 라는 통계 프로파일러도 있습니다. 샘플링 프로파일러이므로 코드에 최소한의 오버헤드를 추가하고 라인 기반(단순한 기능 기반이 아닌) 타이밍을 제공합니다. 게임과 같은 부드러운 실시간 응용 프로그램에 더 적합하지만 cProfile보다 정밀도가 낮을 수 있습니다.

pypi 의 버전은 약간 오래되었으므로 git 저장소 를 지정 pip 로 설치할 수 있습니다.

 pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

다음과 같이 실행할 수 있습니다.

 import statprof with statprof.profile(): my_questionable_function()

https://stackoverflow.com/a/10333592/320036도 참조하십시오.


z0r

서버에서 루트가 아닐 때 lsprofcalltree.py를 사용하고 다음과 같이 프로그램을 실행합니다.

 python lsprofcalltree.py -o callgrind.1 test.py

그런 다음 qcachegrind와 같은 callgrind 호환 소프트웨어로 보고서를 열 수 있습니다.


Vincent Fenet

출처 : http:www.stackoverflow.com/questions/582336/how-can-you-profile-a-python-script

반응형