--Identify bottlenecks to execute code with sufficient speed and lean resource usage --Famous tool for python --Python and timeit
--Extended version of python interactive interpreter --Measure the average execution time by specifying the number of tests (-r) and the number of loops (-n) with the timeit module. --There are two patterns: direct execution of short code and import of code file.
pip install ipython
profiling.py
def fn_arr():
for i in range(1000): arr.append(i)
def fn_ls():
for i in range(1000): ls.append(i)
Single code execution
ipython
In [1]:from array import array
In [2]:arr = array('I', [])
In [3]:%timeit -r 10 -n 10 for i in range(1000): arr.insert(0, i)
10 loops, best of 10: 3.02 ms per loop
In [4]:%timeit -r 10 -n 10 for i in range(1000): ls.insert(0, i)
10 loops, best of 10: 3.8 ms per loop
Run file
ipython
In [1]: from profiling import fn_arr
In [2]: from profiling import fn_ls
In [3]: %timeit -r 10 -n 10 fn_arr()
10 loops, best of 10: 68.6 µs per loop
In [4]: %timeit -r 10 -n 10 fn_ls()
10 loops, best of 10: 8.92 µs per loop
Get the average execution time per loop when 10 loops are executed 10 times
cProfile --Standard profiling tool --Measure the execution time of all functions to be executed
profiling.py
def fn():
l = []
for _ in range(1000000):
l.append('hoge')
l.pop()
fn()
Specify a file and execute
python -m cProfile -s cumulative index.py
2000004 function calls in 23.897 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 23.897 23.897 {built-in method exec}
1 0.000 0.000 23.897 23.897 index.py:1(<module>)
1 12.231 12.231 23.897 23.897 index.py:3(fn)
1000000 5.833 0.000 5.833 0.000 {method 'append' of 'list' objects}
1000000 5.832 0.000 5.832 0.000 {method 'pop' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Output measurement results
python -m cProfile -o profile.stats index.py
Read and display the measurement result file
python
>>> import pstats
>>> p = pstats.Stats('profile.stats')
>>> p.sort_stats('cumulative')
<pstats.Stats object at 0x7f5cca3f0ef0>
>>> p.print_stats()
Sat Nov 28 06:58:28 2015 profile.stats
2000004 function calls in 8.477 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 8.477 8.477 {built-in method exec}
1 0.000 0.000 8.477 8.477 index.py:1(<module>)
1 4.375 4.375 8.477 8.477 index.py:3(fn)
1000000 2.088 0.000 2.088 0.000 {method 'pop' of 'list' objects}
1000000 2.015 0.000 2.015 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
<pstats.Stats object at 0x7fadfcc20f28>
Besides
--print_callers ()
--Caller information
--print_callees ()
--Information when a function calls another function
Etc. can be displayed
line_profiler --A tool that measures the number of times processing is executed and the execution time in line units.
pip install line_profiler
git clone https://github.com/rkern/line_profiler.git
profiling
@profile
def fn():
l = []
for _ in range(1000000):
l.append('hoge')
l.pop()
fn()
> python line_profiler/kernprof.py -l -v index.py
Wrote profile results to index.py.lprof
Timer unit: 1e-06 s
Total time: 8.31965 s
File: index.py
Function: fn at line 2
Line # Hits Time Per Hit % Time Line Contents
==============================================================
2 @profile
3 def fn():
4 1 6 6.0 0.0 l = []
5 1000001 2641832 2.6 31.8 for _ in range(1000000):
6 1000000 2806484 2.8 33.7 l.append('hoge')
7 1000000 2871333 2.9 34.5 l.pop()
--His --Number of times called --Time --Run time --Per Hit --One execution time --% Time --Running time per line relative to total running time
memory_profiler --Memory version of line_profiler
pip install memory_profile
pip install psutil
Similar to line_profiler
> python -m memory_profiler index.py
Filename: index.py
Line # Mem usage Increment Line Contents
================================================
2 10.316 MiB 0.000 MiB @profile
3 def fn():
4 10.320 MiB 0.004 MiB l = []
5 10.320 MiB 0.000 MiB for _ in range(1000000):
6 10.320 MiB 0.000 MiB l.append('hoge')
7 10.320 MiB 0.000 MiB l.pop()
Recommended Posts