Cara menggunakan cProfile untuk membuat profil kode Python

Python mungkin bukan bahasa tercepat, tetapi seringkali cukup cepat. Dan Python sangat ideal ketika waktu programmer lebih penting daripada waktu CPU.

Meskipun demikian, jika aplikasi Python tertentu lamban, Anda tidak diwajibkan untuk menyedotnya begitu saja. Alat yang disertakan dengan instalasi stok interpreter Python dapat memberi Anda umpan balik terperinci tentang bagian mana dari program Anda yang lambat, dan menawarkan beberapa petunjuk tentang cara mempercepatnya.

Cara menggunakan cProfile

The cProfileModul mengumpulkan statistik tentang waktu pelaksanaan program Python. Itu dapat melaporkan apa saja dari seluruh aplikasi hingga satu pernyataan atau ekspresi.

Berikut adalah contoh mainan cara menggunakan cProfile:

def add (x, y): x + = str (y) return x def add_2 (x, y): if y% 20000 == 0: z = [] untuk q dalam range (0,400000): z.append ( q) def main (): a = [] untuk n dalam range (0,200000): tambahkan (a, n) add_2 (a, n) if __name__ == '__main__': import cProfile cProfile.run ('main ( ) ') 

Contoh ini menjalankan fungsi aplikasi main()dan menganalisis kinerja main()dan semua main()panggilan. Dimungkinkan juga untuk menganalisis hanya  sebagian dari program, tetapi penggunaan yang paling umum untuk pemula adalah untuk membuat profil seluruh program.

Jalankan contoh di atas dan Anda akan disambut dengan keluaran seperti berikut:

Apa yang ditampilkan di sini adalah daftar semua panggilan fungsi yang dibuat oleh program, bersama dengan statistik tentang masing-masing:

  • Di bagian atas (baris pertama berwarna biru), kita melihat jumlah panggilan yang dilakukan dalam program profil dan waktu eksekusi total. Anda mungkin juga melihat angka untuk "panggilan primitif", yang berarti panggilan non-rekursif , atau panggilan yang dilakukan langsung ke fungsi yang pada gilirannya tidak memanggil dirinya sendiri lebih jauh di tumpukan panggilan.
  • ncalls : Jumlah panggilan yang dilakukan. Jika Anda melihat dua angka dipisahkan oleh garis miring, angka kedua adalah jumlah panggilan primitif untuk fungsi itu.
  • tottime : Total waktu yang dihabiskan dalam fungsi, tidak termasuk panggilan ke fungsi lain.
  • percall : Rata-rata waktu per panggilan untuk tottime , diperoleh dengan mengambil waktu dan membaginya dengan ncalls .
  • cumtime : Total waktu yang dihabiskan dalam fungsi, termasuk panggilan ke fungsi lain.
  • percall (# 2): Rata-rata waktu per panggilan untuk cumtime ( cumtime dibagi dengan ncalls ).
  • nama file: lineno : Nama file, nomor baris, dan nama fungsi untuk panggilan yang dimaksud.

Bagaimana mengubah laporan cProfile

Secara default, cProfilemengurutkan outputnya dengan "nama standar", yang berarti mengurutkan berdasarkan teks di kolom paling kanan (nama file, nomor baris, dll.).

Format default berguna jika Anda menginginkan laporan umum dari atas ke bawah dari setiap panggilan fungsi untuk referensi. Tetapi jika Anda mencoba untuk sampai ke dasar kemacetan, Anda mungkin ingin bagian program yang paling memakan waktu dicantumkan terlebih dahulu.

Kami dapat menghasilkan hasil ini dengan memohon  cProfile sedikit berbeda. Perhatikan bagaimana bagian bawah program di atas dapat dikerjakan ulang untuk mengurutkan statistik dengan kolom yang berbeda (dalam hal ini ncalls):

jika __name__ == '__main__': import cProfile, pstats profiler = cProfile.Profile () profiler.enable () main () profiler.disable () stats = pstats.Stats (profiler) .sort_stats ('ncalls') stats.print_stats () 

Hasilnya akan terlihat seperti ini:

Beginilah semua ini bekerja:

  • Alih-alih mengeksekusi perintah dengan cara cProfile.run(), yang tidak sangat fleksibel, kita membuat profil objek , profiler.
  • Saat kita ingin membuat profil beberapa tindakan, pertama-tama kita memanggil .enable()instance objek profiler, lalu menjalankan tindakan, lalu memanggil .disable(). (Ini adalah salah satu cara untuk membuat profil hanya sebagian dari program.)
  • The pstatsmodul yang digunakan untuk memanipulasi hasil yang dikumpulkan oleh objek profiler dan mencetak hasil tersebut.

Menggabungkan objek profiler dan pstatsmemungkinkan kita untuk memanipulasi data profil yang diambil - misalnya, untuk mengurutkan statistik yang dihasilkan secara berbeda. Dalam contoh ini, menggunakan .sort_stats('ncalls')mengurutkan statistik berdasarkan ncallskolom. Pilihan sortir lainnya tersedia.

Cara menggunakan hasil cProfile untuk pengoptimalan

Opsi pengurutan yang tersedia untuk cProfile keluaran memungkinkan kita untuk menghilangkan potensi hambatan kinerja dalam suatu program.

ncalls

Bagian informasi pertama dan terpenting yang dapat Anda gali cProfileadalah fungsi mana yang paling sering dipanggil, melalui ncallskolom.

Dalam Python, tindakan membuat pemanggilan fungsi saja akan menimbulkan biaya overhead yang relatif besar. Jika beberapa fungsi dipanggil berulang kali dalam loop yang ketat, meskipun itu bukan fungsi yang berjalan lama, hal itu dijamin akan memengaruhi performa.

Dalam contoh di atas, fungsi add(dan fungsi add_2) dipanggil berulang kali dalam satu putaran. Memindahkan pengulangan ke dalam addfungsi itu sendiri, atau membuat sebaris addfungsi seluruhnya, akan memperbaiki masalah ini.

tottime

Rincian statistik berguna lainnya yang berfungsi program menghabiskan sebagian besar waktunya untuk mengeksekusi, melalui tottimekolom.

Dalam contoh di atas, add_2fungsi menggunakan loop untuk mensimulasikan beberapa komputasi mahal, yang mendorong tottimeskornya ke atas. Fungsi apa pun dengan tottimeskor tinggi harus diperhatikan dengan cermat, terutama jika dipanggil berkali-kali atau dalam loop yang ketat.

Perhatikan bahwa Anda selalu perlu mempertimbangkan konteks  di mana fungsi tersebut digunakan. Jika suatu fungsi memiliki nilai tinggi tottimetetapi hanya dipanggil sekali - misalnya, hanya ketika program dimulai - kemungkinan kecilnya akan menjadi hambatan. Namun, jika Anda mencoba mengurangi waktu startup, Anda pasti ingin tahu apakah fungsi yang dipanggil saat startup membuat yang lainnya menunggu.

Cara mengekspor data cProfile

Jika Anda ingin menggunakan cProfilestatistik yang dihasilkan dengan cara yang lebih maju, Anda dapat mengekspornya ke file data:

stats = pstats.Stats (profiler) stats.dump_stats ('/ path / ke / stats_file.dat') 

File ini dapat dibaca kembali dengan menggunakan pstatsmodul, kemudian diurutkan atau ditampilkan dengan pstats. Data tersebut juga dapat digunakan kembali oleh program lain. Dua contoh:

  • pyprof2calltreemembuat visualisasi terperinci dari grafik panggilan program dan statistik penggunaan dari data profil. Artikel ini memberikan contoh dunia nyata rinci tentang penggunaannya.
  • snakevizjuga menghasilkan visualisasi dari cProfiledata, tetapi menggunakan representasi yang berbeda untuk data - grafik "sunburst" daripada grafik "nyala" pyprof2calltree.

Di luar cProfile untuk profil Python

cProfilebukanlah satu-satunya cara untuk membuat profil aplikasi Python. cProfiletentu saja merupakan salah satu cara yang paling nyaman, mengingat itu dibundel dengan Python. Tapi yang lain perlu diperhatikan.

Satu proyek,, py-spymembuat profil untuk aplikasi Python dengan mengambil sampel aktivitas panggilannya. py-spydapat digunakan untuk memeriksa aplikasi Python yang sedang berjalan tanpa harus menghentikan dan memulai ulang, dan tanpa harus mengubah basis kodenya, sehingga dapat digunakan untuk membuat profil aplikasi yang diterapkan. py-spyjuga menghasilkan beberapa statistik tentang overhead yang dikeluarkan oleh runtime Python (misalnya, overhead pengumpulan sampah), yang cProfiletidak.