파이썬 코드를 한 줄씩 프로파일링하려면 어떻게 해야 합니까?
저는 cProfile을 사용하여 제 코드를 프로파일링하고 있으며, 잘 작동하고 있습니다.저는 또한 gprof2dot.py 을 사용하여 결과를 시각화합니다(조금 더 명확하게).
그러나 cProfile(그리고 지금까지 본 대부분의 다른 Python Profiler)은 함수 호출 수준에서만 프로파일링하는 것 같습니다.이것은 특정 기능이 다른 장소에서 호출될 때 혼란을 일으킵니다. 1번 호출이나 2번 호출이 대부분을 차지하는지 모르겠습니다.이것은 문제의 기능이 다른 7곳에서 호출된 6단계 깊이일 때 더욱 악화됩니다.
라인별 프로파일링은 어떻게 해야 합니까?
이 대신:
function #12, total time: 2.0s
저는 다음과 같은 것을 보고 싶습니다.
function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s
cProfile은 전체 시간 중 부모에게 "전송"하는 시간을 표시하지만, 계층이 여러 개이고 상호 연결된 호출이 있을 때는 이 연결이 손실됩니다.
이상적으로는 데이터를 구문 분석한 다음 각 줄에 총 시간이 주어진 소스 파일을 보여주는 GUI를 갖고 싶습니다.이와 같은 것:
main.py:
a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s
그런 다음 두 번째 "func(c)" 통화를 클릭하여 "func(a)" 통화와 별도로 해당 통화에서 무엇이 시간을 차지하는지 확인할 수 있습니다.이해 하셨나요?
저는 그것이 로버트 컨의 line_profiler가 의도한 것이라고 생각합니다.링크에서:
File: pystone.py
Function: Proc2 at line 149
Total time: 0.606656 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
149 @profile
150 def Proc2(IntParIO):
151 50000 82003 1.6 13.5 IntLoc = IntParIO + 10
152 50000 63162 1.3 10.4 while 1:
153 50000 69065 1.4 11.4 if Char1Glob == 'A':
154 50000 66354 1.3 10.9 IntLoc = IntLoc - 1
155 50000 67263 1.3 11.1 IntParIO = IntLoc - IntGlob
156 50000 65494 1.3 10.8 EnumLoc = Ident1
157 50000 68001 1.4 11.2 if EnumLoc == Ident1:
158 50000 63739 1.3 10.5 break
159 50000 61575 1.2 10.1 return IntParIO
pprofile(pypi)도 사용할 수 있습니다.전체 실행을 프로파일링하려면 소스 코드를 수정할 필요가 없습니다.다음 두 가지 방법으로 더 큰 프로그램의 하위 집합을 프로파일링할 수도 있습니다.
코드의 특정 지점에 도달하면 프로파일링을 전환합니다. 예를 들어 다음과 같습니다.
import pprofile profiler = pprofile.Profile() with profiler: some_code # Process profile content: generate a cachegrind file and send it to user. # You can also write the result to the console: profiler.print_stats() # Or to a file: profiler.dump_stats("/tmp/profiler_stats.txt")
통계 프로파일링을 사용하여 호출 스택에서 비동기적으로 프로파일링을 전환합니다(예: 신호 처리기 또는 사용 가능한 작업자 스레드).
import pprofile profiler = pprofile.StatisticalProfile() statistical_profiler_thread = pprofile.StatisticalThread( profiler=profiler, ) with statistical_profiler_thread: sleep(n) # Likewise, process profile content
코드 주석 출력 형식은 라인 프로파일러와 매우 유사합니다.
$ pprofile --threads 0 demo/threads.py
Command line: ['demo/threads.py']
Total duration: 1.00573s
File: demo/threads.py
File duration: 1.00168s (99.60%)
Line #| Hits| Time| Time per hit| %|Source code
------+----------+-------------+-------------+-------+-----------
1| 2| 3.21865e-05| 1.60933e-05| 0.00%|import threading
2| 1| 5.96046e-06| 5.96046e-06| 0.00%|import time
3| 0| 0| 0| 0.00%|
4| 2| 1.5974e-05| 7.98702e-06| 0.00%|def func():
5| 1| 1.00111| 1.00111| 99.54%| time.sleep(1)
6| 0| 0| 0| 0.00%|
7| 2| 2.00272e-05| 1.00136e-05| 0.00%|def func2():
8| 1| 1.69277e-05| 1.69277e-05| 0.00%| pass
9| 0| 0| 0| 0.00%|
10| 1| 1.81198e-05| 1.81198e-05| 0.00%|t1 = threading.Thread(target=func)
(call)| 1| 0.000610828| 0.000610828| 0.06%|# /usr/lib/python2.7/threading.py:436 __init__
11| 1| 1.52588e-05| 1.52588e-05| 0.00%|t2 = threading.Thread(target=func)
(call)| 1| 0.000438929| 0.000438929| 0.04%|# /usr/lib/python2.7/threading.py:436 __init__
12| 1| 4.79221e-05| 4.79221e-05| 0.00%|t1.start()
(call)| 1| 0.000843048| 0.000843048| 0.08%|# /usr/lib/python2.7/threading.py:485 start
13| 1| 6.48499e-05| 6.48499e-05| 0.01%|t2.start()
(call)| 1| 0.00115609| 0.00115609| 0.11%|# /usr/lib/python2.7/threading.py:485 start
14| 1| 0.000205994| 0.000205994| 0.02%|(func(), func2())
(call)| 1| 1.00112| 1.00112| 99.54%|# demo/threads.py:4 func
(call)| 1| 3.09944e-05| 3.09944e-05| 0.00%|# demo/threads.py:7 func2
15| 1| 7.62939e-05| 7.62939e-05| 0.01%|t1.join()
(call)| 1| 0.000423908| 0.000423908| 0.04%|# /usr/lib/python2.7/threading.py:653 join
16| 1| 5.26905e-05| 5.26905e-05| 0.01%|t2.join()
(call)| 1| 0.000320196| 0.000320196| 0.03%|# /usr/lib/python2.7/threading.py:653 join
pprofile은 코드 수정에 의존하지 않기 때문에 프로그램 시작 시간(모듈 가져오기, 글로벌 초기화 등)을 프로파일링할 수 있도록 최상위 모듈 문을 프로파일링할 수 있습니다.
캐시 그리드 형식의 출력을 생성할 수 있으므로 kcache grind를 사용하여 큰 결과를 쉽게 찾아볼 수 있습니다.
공개:저는 프로필 작성자입니다.
위에서 언급한 @Joe Kington의 답변을 개선하기 위해서입니다.
Python 3.x의 경우 line_profiler를 사용합니다.
설치:
pip install line_profiler
용도:
이 있다고 .main.py
그에서 기능은 고그안서, 기들능입니다.fun_a()
그리고.fun_b()
것; ; 합장사용야니해다를식가당신은간과▁that▁the합.@profile
함수 정의 바로 앞에 있습니다.예를 들어,
@profile
def fun_a():
#do something
@profile
def fun_b():
#do something more
if __name__ == '__main__':
fun_a()
fun_b()
셸 명령을 실행하여 프로그램을 프로파일링할 수 있습니다.
$ kernprof -l -v main.py
는 인는다음사가수있습다니져올여를 사용하여 수 .$ kernprof -h
Usage: kernprof [-s setupfile] [-o output_file_path] scriptfile [arg] ...
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-l, --line-by-line Use the line-by-line profiler from the line_profiler
module instead of Profile. Implies --builtin.
-b, --builtin Put 'profile' in the builtins. Use 'profile.enable()'
and 'profile.disable()' in your code to turn it on and
off, or '@profile' to decorate a single function, or
'with profile:' to profile a single section of code.
-o OUTFILE, --outfile=OUTFILE
Save stats to <outfile>
-s SETUP, --setup=SETUP
Code to execute before the code to profile
-v, --view View the results of the profile in addition to saving
it.
결과는 콘솔에 다음과 같이 인쇄됩니다.
Total time: 17.6699 s
File: main.py
Function: fun_a at line 5
Line # Hits Time Per Hit % Time Line Contents
==============================================================
5 @profile
6 def fun_a():
...
편집: 프로파일러의 결과는 TAMPPA 패키지를 사용하여 구문 분석할 수 있습니다.이를 사용하면 다음과 같이 라인별로 원하는 플롯을 얻을 수 있습니다.
이에 대해 line_profiler 패키지의 도움을 받을 수 있습니다.
먼저 패키지를 설치합니다.
pip install line_profiler
마법 명령을 사용하여 패키지를 파이썬/노트북 환경에 로드
%load_ext line_profiler
과 같이 .
다음과 같이 합니다.
%lprun -f demo_func demo_func(arg1, arg2)
다음 단계를 따르면 모든 세부 정보가 포함된 포맷된 출력을 얻을 수 있습니다 :)
Line # Hits Time Per Hit % Time Line Contents
1 def demo_func(a,b):
2 1 248.0 248.0 64.8 print(a+b)
3 1 40.0 40.0 10.4 print(a)
4 1 94.0 94.0 24.5 print(a*b)
5 1 1.0 1.0 0.3 return a/b
PyVmMonitor에는 실행 중인 프로그램에 연결하여 통계를 얻을 수 있는 실시간 보기가 있습니다.
참조: http://www.pyvmmonitor.com/
언급URL : https://stackoverflow.com/questions/3927628/how-can-i-profile-python-code-line-by-line
'programing' 카테고리의 다른 글
소수점 다음에 숫자를 얻는 방법은? (0) | 2023.06.07 |
---|---|
새 아스퍼.NetMVC5 프로젝트는 로그인 페이지에 대한 무한 루프를 생성합니다. (0) | 2023.06.07 |
Firebase 스토리지에서 전체 폴더를 다운로드하는 방법은 무엇입니까? (0) | 2023.06.07 |
web.xml이 누락되었으며 true로 설정되었습니다. (0) | 2023.06.02 |
왜 사람들은 루비가 느리다고 말합니까? (0) | 2023.06.02 |