Project Euler dan kontes pengkodean lainnya sering kali memiliki waktu maksimum untuk dijalankan atau orang-orang membanggakan seberapa cepat solusi khusus mereka berjalan. Dengan Python, terkadang pendekatannya agak kludgey - yaitu menambahkan kode waktu ke __main__
.
Apa cara yang baik untuk membuat profil berapa lama program Python perlu dijalankan?
python
performance
profiling
time-complexity
Chris Lawlor
sumber
sumber
Jawaban:
Python menyertakan profiler yang disebut cProfile . Ini tidak hanya memberikan total waktu berjalan, tetapi juga kali setiap fungsi secara terpisah, dan memberi tahu Anda berapa kali setiap fungsi dipanggil, sehingga memudahkan untuk menentukan di mana Anda harus melakukan optimasi.
Anda dapat memanggilnya dari dalam kode Anda, atau dari penerjemah, seperti ini:
Yang lebih bermanfaat lagi, Anda dapat menjalankan cProfile saat menjalankan skrip:
Untuk membuatnya lebih mudah, saya membuat file batch kecil yang disebut 'profile.bat':
Jadi yang harus saya lakukan adalah menjalankan:
Dan saya mendapatkan ini:
EDIT: Tautan yang diperbarui ke sumber video yang bagus dari PyCon 2013 berjudul Python Profiling
Juga melalui YouTube .
sumber
python -m cProfile -o <out.profile> <script>
), RunSnakeRun , dipanggil sebagairunsnake <out.profile>
sangat berharga.cprofile
masih dianjurkan lebihprofile
.Beberapa waktu lalu saya membuat
pycallgraph
yang menghasilkan visualisasi dari kode Python Anda. Sunting: Saya telah memperbarui contoh untuk bekerja dengan 3.3, rilis terbaru pada tulisan ini.Setelah a
pip install pycallgraph
dan menginstal GraphViz Anda dapat menjalankannya dari baris perintah:Atau, Anda dapat membuat profil bagian tertentu dari kode Anda:
Salah satu dari ini akan menghasilkan
pycallgraph.png
file yang mirip dengan gambar di bawah ini:sumber
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
.Perlu ditunjukkan bahwa menggunakan profiler hanya berfungsi (secara default) pada utas utama, dan Anda tidak akan mendapatkan informasi dari utas lain jika Anda menggunakannya. Ini bisa menjadi semacam gotcha karena sepenuhnya tidak disebutkan dalam dokumentasi profiler .
Jika Anda juga ingin membuat utas profil, Anda akan ingin melihat
threading.setprofile()
fungsi di dokumen.Anda juga dapat membuat
threading.Thread
subclass sendiri untuk melakukannya:dan gunakan
ProfiledThread
kelas itu alih-alih yang standar. Mungkin memberi Anda lebih banyak fleksibilitas, tapi saya tidak yakin itu layak, terutama jika Anda menggunakan kode pihak ketiga yang tidak akan menggunakan kelas Anda.sumber
target
, yang dilakukan olehthreading.Thread.run()
panggilan tersebut. Tapi seperti yang saya katakan di jawaban, mungkin tidak layak untuk subkelas Thread, karena kode pihak ketiga mana pun tidak akan menggunakannya, dan sebagai gantinya digunakanthreading.setprofile()
.Wiki python adalah halaman yang bagus untuk profil sumber daya: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
seperti halnya python docs: http://docs.python.org/library/profile.html
seperti yang ditunjukkan oleh Chris Lawlor cProfile adalah alat yang hebat dan dapat dengan mudah digunakan untuk mencetak ke layar:
atau ke file:
PS> Jika Anda menggunakan Ubuntu, pastikan untuk menginstal profil python
Jika Anda menghasilkan file Anda bisa mendapatkan visualisasi yang bagus menggunakan alat berikut
PyCallGraph: alat untuk membuat gambar panggilan grafik
menginstal:
Lari:
melihat:
Anda dapat menggunakan apa pun yang Anda suka untuk melihat file png, saya menggunakan gimp
Sayangnya saya sering mendapatkannya
dot: grafik terlalu besar untuk bitmap cairo-renderer. Penskalaan 0,257079 agar sesuai
yang membuat gambar saya luar biasa kecil. Jadi saya biasanya membuat file svg:
PS> pastikan untuk menginstal graphviz (yang menyediakan program dot):
Grafik Alternatif menggunakan gprof2dot melalui @maxy / @quodlibetor:
sumber
@ Maxy mengomentari jawaban ini cukup membantu saya sehingga saya pikir itu layak jawaban sendiri: Saya sudah punya file .pstats yang dihasilkan cProfile dan saya tidak ingin menjalankan kembali hal-hal dengan pycallgraph, jadi saya menggunakan gprof2dot , dan mendapatkan cukup svgs:
dan BLAM!
Ia menggunakan dot (hal yang sama yang digunakan pycallgraph) sehingga output terlihat serupa. Saya mendapat kesan bahwa gprof2dot kehilangan lebih sedikit informasi:
sumber
pwd
/gprof2dot/gprof2dot.py $ HOME / bin (atau gunakan ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin di sebagian besar shell - aksen kubur diambil sebagai pemformatan terlebih dahulu saat memformat terlebih dahulu Versi: kapan).ln
's argumen-urutan yang salah hampir setiap waktu.Saya berlari ke alat yang berguna yang disebut SnakeViz ketika meneliti topik ini. SnakeViz adalah alat visualisasi profiling berbasis web. Sangat mudah untuk menginstal dan menggunakan. Cara biasa saya menggunakannya adalah untuk menghasilkan file stat dengan
%prun
dan kemudian melakukan analisis di SnakeViz.Teknik utama yaitu yang digunakan adalah grafik Sunburst seperti yang ditunjukkan di bawah ini, di mana hirarki panggilan fungsi diatur sebagai lapisan busur dan info waktu dikodekan dalam lebar sudutnya.
Yang terbaik adalah Anda bisa berinteraksi dengan bagan. Sebagai contoh, untuk memperbesar satu dapat mengklik pada busur, dan busur dan turunannya akan diperbesar sebagai sunburst baru untuk menampilkan rincian lebih lanjut.
sumber
Cara termudah dan tercepat untuk menemukan ke mana perginya waktu.
Menggambar diagram lingkaran di browser. Bagian terbesar adalah fungsi masalah. Sangat sederhana.
sumber
Saya pikir itu
cProfile
bagus untuk profil, sementarakcachegrind
bagus untuk memvisualisasikan hasil. Dipyprof2calltree
antara menangani konversi file.Untuk menginstal alat yang diperlukan (setidaknya di Ubuntu):
Hasil:
sumber
brew install qcachegrind
dan masingkcachegrind
- masing denganqcachegrind
dalam keterangan untuk berhasil membuat profil.export QT_X11_NO_MITSHM=1
Juga layak disebutkan adalah penampil dump GUI cProfile RunSnakeRun . Ini memungkinkan Anda untuk mengurutkan dan memilih, sehingga memperbesar bagian yang relevan dari program. Ukuran persegi panjang dalam gambar sebanding dengan waktu yang dibutuhkan. Jika Anda mengarahkan mouse di atas persegi panjang itu menyoroti panggilan itu di dalam tabel dan di mana-mana di peta. Ketika Anda mengklik dua kali pada persegi panjang itu memperbesar bagian itu. Ini akan menunjukkan kepada Anda siapa yang memanggil bagian itu dan apa yang bagian itu panggilan.
Informasi deskriptif sangat membantu. Ini menunjukkan kepada Anda kode untuk bit yang dapat membantu ketika Anda berurusan dengan panggilan perpustakaan built-in. Ini memberi tahu Anda file apa dan baris apa untuk menemukan kode.
Juga ingin menunjukkan bahwa OP mengatakan 'profiling' tetapi sepertinya dia maksudkan 'timing'. Perlu diingat program akan berjalan lebih lambat saat diprofilkan.
sumber
Modul profil yang bagus adalah line_profiler (dipanggil menggunakan skrip kernprof.py). Itu bisa diunduh di sini .
Pemahaman saya adalah bahwa cProfile hanya memberikan informasi tentang total waktu yang dihabiskan di setiap fungsi. Jadi setiap baris kode tidak diberi batas waktu. Ini adalah masalah dalam komputasi ilmiah karena seringkali satu baris tunggal dapat mengambil banyak waktu. Juga, seingat saya, cProfile tidak mengetahui waktu yang saya habiskan di katakanlah numpy.dot.
sumber
Baru-baru ini saya membuat tuna untuk memvisualisasikan runtime Python dan mengimpor profil; ini mungkin membantu di sini.
Instal dengan
Buat profil runtime
atau profil impor (diperlukan Python 3.7+)
Kemudian jalankan tuna pada file
sumber
profil
line_profiler
(sudah disajikan di sini) juga terinspirasipprofile
, yang digambarkan sebagai:Ini memberikan garis-granularitas sebagai
line_profiler
, adalah Python murni, dapat digunakan sebagai perintah mandiri atau modul, dan bahkan dapat menghasilkan file format callgrind yang dapat dengan mudah dianalisis[k|q]cachegrind
.vprof
Ada juga vprof , paket Python yang dideskripsikan sebagai:
sumber
Ada banyak jawaban bagus tetapi mereka menggunakan baris perintah atau program eksternal untuk membuat profil dan / atau mengurutkan hasilnya.
Saya benar-benar merindukan cara yang bisa saya gunakan dalam IDE saya (eclipse-PyDev) tanpa menyentuh baris perintah atau menginstal apa pun. Jadi begini.
Pembuatan profil tanpa baris perintah
Lihat dokumen atau jawaban lain untuk info lebih lanjut.
sumber
Mengikuti jawaban Joe Shaw tentang kode multi-utas untuk tidak berfungsi seperti yang diharapkan, saya menduga bahwa
runcall
metode di cProfile hanya melakukanself.enable()
danself.disable()
memanggil sekitar panggilan fungsi yang diprofilkan, sehingga Anda dapat melakukannya sendiri dan memiliki kode apa pun yang Anda inginkan di antaranya. gangguan minimal dengan kode yang ada.sumber
cprofile.py
's kode sumber mengungkapkan itu persis apa yangruncall()
dilakukannya. Menjadi lebih spesifik, setelah membuat instance Profil denganprof = cprofile.Profile()
, segera panggilprof.disable()
, lalu tambahkanprof.enable()
danprof.disable()
panggil di sekitar bagian kode yang ingin Anda profil.Dalam sumber Virtaal ada kelas dan dekorator yang sangat berguna yang dapat membuat profil (bahkan untuk metode / fungsi tertentu) sangat mudah. Outputnya kemudian dapat dilihat dengan sangat nyaman di KCacheGrind.
sumber
cProfile sangat bagus untuk profil cepat tetapi sebagian besar waktu itu berakhir untuk saya dengan kesalahan. Fungsi runctx memecahkan masalah ini dengan menginisialisasi dengan benar lingkungan dan variabel, semoga bermanfaat bagi seseorang:
sumber
Jika Anda ingin membuat profiler kumulatif, artinya menjalankan fungsi beberapa kali berturut-turut dan menonton jumlah hasilnya.
Anda dapat menggunakan
cumulative_profiler
dekorator ini :itu python> = 3,6 spesifik, tetapi Anda dapat menghapusnya
nonlocal
agar berfungsi pada versi yang lebih lama.Contoh
membuat profil fungsi
baz
baz
berlari 5 kali dan mencetak ini:menentukan jumlah kali
sumber
Solusi terminal saja (dan paling sederhana), jika semua UI mewah gagal untuk menginstal atau menjalankan:
abaikan
cProfile
sepenuhnya dan ganti denganpyinstrument
, yang akan mengumpulkan dan menampilkan pohon panggilan segera setelah eksekusi.Install:
Profil dan hasil tampilan:
Bekerja dengan python2 dan 3.
[EDIT] Dokumentasi API, untuk profil hanya sebagian dari kode, dapat ditemukan di sini .
sumber
Cara saya adalah menggunakan yappi ( https://github.com/sumerc/yappi ). Ini sangat berguna dikombinasikan dengan server RPC di mana (bahkan hanya untuk debugging) Anda mendaftar metode untuk memulai, menghentikan dan mencetak informasi profil, misalnya dengan cara ini:
Kemudian ketika program Anda bekerja, Anda dapat memulai profiler kapan saja dengan memanggil
startProfiler
metode RPC dan membuang informasi profil ke file log dengan memanggilprintProfiler
(atau memodifikasi metode rpc untuk mengembalikannya ke pemanggil) dan mendapatkan output seperti:Ini mungkin tidak terlalu berguna untuk skrip pendek tetapi membantu untuk mengoptimalkan proses tipe server terutama mengingat
printProfiler
metode ini dapat dipanggil beberapa kali dari waktu ke waktu untuk profil dan membandingkan misalnya skenario penggunaan program yang berbeda.Dalam versi yappi yang lebih baru, kode berikut akan berfungsi:
sumber
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 setelah mencoba beberapa kali untuk menyisipkan blok kode ke dalam komentar yang saya berikan. Ini sangat sulit untuk situs tanya jawab yang berorientasi pemrograman. )Alat baru untuk menangani profil dengan Python adalah PyVmMonitor: http://www.pyvmmonitor.com/
Ini memiliki beberapa fitur unik seperti
Catatan: ini komersial, tetapi gratis untuk sumber terbuka.
sumber
gprof2dot_magic
Fungsi ajaib untuk
gprof2dot
memrofilkan pernyataan Python sebagai grafik DOT di JupyterLab atau Jupyter Notebook.Repo GitHub: https://github.com/mattijn/gprof2dot_magic
instalasi
Pastikan Anda memiliki paket Python
gprof2dot_magic
.Ketergantungannya
gprof2dot
dangraphviz
akan diinstal jugapemakaian
Untuk mengaktifkan fungsi sulap, muat
gprof2dot_magic
modul terlebih dahuludan kemudian profil setiap pernyataan garis sebagai grafik DOT seperti itu:
sumber
https://github.com/amoffat/Inspect-Shell
Anda bisa menggunakannya (dan jam tangan Anda).
sumber
Untuk menambahkan ke https://stackoverflow.com/a/582337/1070617 ,
Saya menulis modul ini yang memungkinkan Anda menggunakan cProfile dan melihat hasilnya dengan mudah. Lebih lanjut di sini: https://github.com/ymichael/cprofilev
Lihat juga: http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html tentang cara memahami statistik yang dikumpulkan.
sumber
Itu akan tergantung pada apa yang ingin Anda lihat dari profil. Metrik waktu sederhana dapat diberikan oleh (bash).
Bahkan '/ usr / bin / time' dapat menampilkan metrik terperinci dengan menggunakan flag '--verbose'.
Untuk memeriksa metrik waktu yang diberikan oleh masing-masing fungsi dan untuk lebih memahami berapa banyak waktu yang dihabiskan untuk fungsi, Anda bisa menggunakan cProfile inbuilt dengan python.
Memasuki metrik yang lebih rinci seperti kinerja, waktu bukanlah satu-satunya metrik. Anda dapat khawatir tentang memori, utas dll.
Opsi pembuatan profil:
1. line_profiler adalah profiler lain yang biasa digunakan untuk mengetahui metrik pewaktu baris demi baris.
2. memory_profiler adalah alat untuk profil penggunaan memori.
3. heapy (from project Guppy) Profil bagaimana objek di heap digunakan.
Ini adalah beberapa yang umum saya cenderung gunakan. Tetapi jika Anda ingin mencari tahu lebih banyak, cobalah membaca buku ini. Ini adalah buku yang cukup bagus untuk memulai dengan mempertimbangkan kinerja. Anda dapat beralih ke topik lanjutan tentang menggunakan python yang dikompilasi Cython dan JIT (Just-in-time).
sumber
Dengan profiler statistik seperti austin , tidak diperlukan instrumentasi, artinya Anda bisa mendapatkan data profiling dari aplikasi Python hanya dengan
Output mentah tidak terlalu berguna, tetapi Anda dapat menyalurkannya ke flamegraph.pl untuk mendapatkan representasi grafik nyala dari data yang memberi Anda rincian tempat waktu (diukur dalam mikrodetik waktu nyata) dihabiskan.
sumber
Untuk mendapatkan statistik profil cepat pada notebook IPython. Seseorang bisa menanamkan line_profiler dan memory_profiler langsung ke notebook mereka.
Paket bermanfaat lainnya adalah Pympler . Ini adalah paket profil yang kuat yang mampu melacak kelas, objek, fungsi, kebocoran memori, dll. Contoh di bawah ini, Documents terlampir.
Mendapatkan!
Muat itu!
Gunakan!
%waktu
Memberi:
% timeit
% prun
Memberi:
% memit
Memberi:
% lprun
Memberi:
sys.getsizeof
Mengembalikan ukuran objek dalam byte.
asizeof () dari pympler
pympler.asizeof dapat digunakan untuk menyelidiki berapa banyak memori yang dikonsumsi objek Python tertentu. Berbeda dengan sys.getsizeof, ukuran objek asizeof rekursif
pelacak dari pympler
Melacak masa pakai suatu fungsi.
Paket Pympler terdiri dari sejumlah besar fungsi utilitas tinggi untuk kode profil. Semuanya tidak dapat dibahas di sini. Lihat dokumentasi terlampir untuk implementasi profil verbose.
Dok Pympler
sumber
Ada juga profiler statistik yang disebut
statprof
. Ini adalah profiler pengambilan sampel, sehingga menambahkan overhead minimal ke kode Anda dan memberikan pengaturan waktu berbasis garis (bukan hanya berdasarkan fungsi). Ini lebih cocok untuk aplikasi real-time lunak seperti game, tetapi mungkin memiliki presisi kurang dari cProfile.The Versi di pypi agak tua, sehingga dapat menginstalnya dengan
pip
dengan menentukan repositori git :Anda dapat menjalankannya seperti ini:
Lihat juga https://stackoverflow.com/a/10333592/320036
sumber
Saya baru saja mengembangkan profiler saya sendiri yang terinspirasi dari pypref_time:
https://github.com/modaresimr/auto_profiler
Dengan menambahkan dekorator itu akan menunjukkan pohon fungsi yang memakan waktu
@Profiler(depth=4, on_disable=show)
Contoh
Contoh Output
sumber
Ketika saya tidak melakukan root pada server, saya menggunakan lsprofcalltree.py dan menjalankan program saya seperti ini:
Kemudian saya dapat membuka laporan dengan perangkat lunak yang kompatibel dengan callgrind, seperti qcachegrind
sumber