Bir Python betiğini nasıl profilleyebilirsiniz?


1283

Project Euler ve diğer kodlama yarışmalarının genellikle maksimum çalışması için zamanları vardır veya insanlar belirli çözümlerinin ne kadar hızlı çalıştığından övünürler. Python ile, bazen yaklaşımlar biraz kludgey - yani, zamanlama kodu ekleyerek __main__.

Bir Python programının çalıştırılmasının ne kadar sürdüğünü belirlemenin iyi bir yolu nedir?


113
Proje euler programlarının profillenmesine gerek olmamalıdır. Ya bir dakikadan kısa sürede çalışan bir algoritmaya sahipsiniz ya da tamamen yanlış algoritmaya sahipsiniz. "Ayarlama" nadiren uygundur. Genellikle yeni bir yaklaşım benimsemeniz gerekir.
S.Lott

105
S.Lott: Profil oluşturma genellikle hangi alt programların yavaş olduğunu belirlemede yardımcı bir yöntemdir. Uzun süren altyordamlar algoritmik iyileştirme için mükemmel adaylardır.
stalepretzel

Yanıtlar:


1369

Python, cProfile adlı bir profil oluşturucu içerir . Sadece toplam çalışma süresini vermekle kalmaz, aynı zamanda her bir işlevi ayrı ayrı zamanlar ve size her bir işlevin kaç kez çağrıldığını söyler, böylece optimizasyonları nerede yapmanız gerektiğini belirlemeyi kolaylaştırır.

Kodu kodunuzdan veya yorumlayıcıdan şöyle çağırabilirsiniz:

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

Daha da kullanışlı olan bir komut dosyası çalıştırırken cProfile'ı çağırabilirsiniz:

python -m cProfile myscript.py

Daha da kolaylaştırmak için, 'profile.bat' adlı küçük bir toplu iş dosyası hazırladım:

python -m cProfile %1

Tek yapmam gereken koşmak:

profile euler048.py

Ve bunu anladım:

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}

DÜZENLEME: PyCon 2013'ten Python Profil Oluşturma başlıklı iyi bir video kaynağı bağlantısı
da YouTube üzerinden güncellendi .


251
Ayrıca, -s anahtarı ile yapılabilecek sonuçları sıralamak yararlıdır, örnek: '-s time'. Kümülatif / ad / saat / dosya sıralama seçeneklerini kullanabilirsiniz.
Jiri

19
Ayrıca,% prun (profil çalıştırma) sihirli işlevini kullanarak ipython'dan cProfile modülünü kullanabileceğinizi belirtmek gerekir. Önce modülünüzü içe aktarın ve ardından% prun ile ana işlevi çağırın: import euler048; % prun euler048.main ()
RussellStewart

53
CProfile dökümlerini (oluşturduğu python -m cProfile -o <out.profile> <script>) görselleştirmek için , RunSnakeRun , olduğu gibi çağrılır runsnake <out.profile>.
Lily Chung

13
@NeilG python 3 için bile cprofile, hala tavsiye edilir profile.
trichoplax

17
CProfile dökümlerini görselleştirmek için RunSnakeRun 2011'den beri güncellenmemiştir ve python3'ü desteklememektedir. Sen kullanmalıdır snakeviz yerine
Giacomo Tecya Pigani

423

Bir süre önce pycallgraphPython kodunuzdan bir görselleştirme üreten bir şey yaptım . Düzenleme: Bu yazının son sürümü olan 3.3 ile çalışmak için örneği güncelledim.

GraphViz'i yükleyippip install pycallgraph kurduktan sonra komut satırından çalıştırabilirsiniz:

pycallgraph graphviz -- ./mypythonscript.py

Veya kodunuzun belirli bölümlerini profilleyebilirsiniz:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

Bunlardan her ikisi de pycallgraph.pngaşağıdaki görüntüye benzer bir dosya oluşturur :

resim açıklamasını buraya girin


43
Çağrı sayısına göre renklendiriyor musunuz? Eğer öyleyse, zamana göre renklendirmelisiniz çünkü en fazla çağrıya sahip fonksiyon her zaman en çok zaman alan işlev değildir.
kırmızı

21
@red Renkleri istediğiniz gibi ve hatta her ölçüm için bağımsız olarak özelleştirebilirsiniz. Örneğin aramalar için kırmızı, zaman için mavi, bellek kullanımı için yeşil.
gak

2
Bu hatayı alıyorumTraceback (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
Ciasto piekarz

3
Bunu, şeylerin açıklandığı gibi çalışması için GraphViz'i yüklemeniz gerektiğini belirtmek için güncelledim. Ubuntu'da bu sadece sudo apt-get install graphviz.
mlissner

2
Bu yüklemek için biraz çalışma gerektirir burada yardımcı olmak için 3 adımdır. 1. pip ile kurun, 2. exe üzerinden GraphViz yükleyin 3. GraphViz dizinine yol değişkenleri ayarlayın 4. Diğer tüm hataların nasıl düzeltileceğini öğrenin. 5. png dosyasını nereye kaydettiğini öğrenin?
Bataklık

199

Profiler kullanmanın yalnızca ana iş parçacığında (varsayılan olarak) çalıştığını ve bunları kullanırsanız diğer iş parçacıklarından herhangi bir bilgi alamayacağınızı belirtmek gerekir. Profiler belgelerinde tamamen belirtilmemiş olduğu için bu bir gotcha olabilir .

İleti dizilerini de profillemek istiyorsanız , dokümanlardaki threading.setprofile()işleve bakmak istersiniz .

Bunu threading.Threadyapmak için kendi alt sınıfınızı da oluşturabilirsiniz :

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,))

ve ProfiledThreadstandart sınıf yerine bu sınıfı kullanın. Size daha fazla esneklik verebilir, ancak buna değmeyeceğinden emin değilim, özellikle de sınıfınızı kullanmayacak üçüncü taraf kodlarını kullanıyorsanız.


1
Belgelerde de runcall'a referans görmüyorum. CProfile.py bir göz vererek, neden threading.Thread.run işlevi ne de argüman olarak kullandığınızdan emin değilim. Burada başka bir iş parçacığının çalışma yöntemine bir başvuru görmek beklenirdi .
PypeBros

Belgelerde değil, modülde. Bkz. Hg.python.org/cpython/file/6bf07db23445/Lib/cProfile.py#l140 . Bu, belirli bir işlev çağrısını profillemenize olanak tanır ve bizim durumumuzda, iş parçacığının yürüttüğü iş parçacığının targetişlevini profillemek istiyoruz threading.Thread.run(). Ancak cevabımda söylediğim gibi, muhtemelen herhangi bir üçüncü taraf kodu kullanamayacağı ve bunun yerine kullanacağı için Thread'ı alt sınıflamaya değmez threading.setprofile().
Joe Shaw

9
kodu profiler.enable () ve profiler.disable () ile sarmak da oldukça iyi çalışıyor. Temelde runcall bunu yapar ve herhangi bir sayıda argümanı veya benzeri şeyi zorlamaz.
PypeBros


1
Joe, profillerin Python 3.4'te asyncio ile nasıl oynadığını biliyor musun?
Nick Chammas

148

Python wiki, kaynak oluşturma için harika bir sayfadır: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

python belgeleri gibi: http://docs.python.org/library/profile.html

Chris Lawlor cProfile tarafından gösterildiği gibi harika bir araçtır ve ekrana yazdırmak için kolayca kullanılabilir:

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

veya dosyaya:

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

PS> Ubuntu kullanıyorsanız, python-profili yüklediğinizden emin olun

apt-get install python-profiler 

Dosyaya çıktı alırsanız, aşağıdaki araçları kullanarak güzel görselleştirmeler alabilirsiniz

PyCallGraph: çağrı grafik görüntüleri oluşturmak için bir araç
yükleyin:

 pip install pycallgraph

Çalıştırmak:

 pycallgraph mine.py args

görünüm:

 gimp pycallgraph.png

Png dosyasını görüntülemek için ne istersen kullanabilirsiniz, gimp kullandım
Ne yazık ki sık sık alıyorum

nokta: grafik, cairo-oluşturucu bitmap'leri için çok büyük. Sığacak şekilde 0,257079 oranında ölçeklendirme

bu da görüntülerimi alışılmadık derecede küçük yapıyor. Bu yüzden genellikle svg dosyaları oluşturuyorum:

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

PS> graphviz'i (nokta programını sağlayan) yüklediğinizden emin olun:

pip install graphviz

@Maxy / @quodlibetor ile gprof2dot kullanarak alternatif grafik oluşturma:

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

12
gprof2dot bu grafikleri de yapabilir. Bence çıktı biraz daha güzel ( örnek ).
maxy


134

@ Maxy'nin bu cevaba yaptığı yorum bana kendi cevabını hak ettiğini düşündüğümde bana yardımcı oldu: Zaten cProfile tarafından oluşturulan .pstats dosyaları vardı ve pycallgraph ile işleri yeniden çalıştırmak istemedim, bu yüzden gprof2dot kullandım ve güzel aldım SVG lezyonu:

$ 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

ve BLAM!

Nokta kullanır (pikallgrafın kullandığı şeyle), böylece çıktı benzer görünür. Gprof2dot daha az bilgi kaybediyor izlenimi alıyorum:

gprof2dot örnek çıktı


1
İyi yaklaşım, Chrome'da SVG'yi görüntüleyebildiğiniz ve yukarı / aşağı ölçeklendirebildiğiniz için gerçekten iyi çalışır. Üçüncü satır yazım hatası olmalıdır: ln -s pwd/gprof2dot/gprof2dot.py $ HOME / bin (veya ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin çoğu kabukta biçimlendirilir - önce mezar aksanı biçimlendirme olarak alınır versiyon).
RichVel

2
Ah, iyi bir noktaya değindin. lnNeredeyse her seferinde argüman sırasını yanlış alıyorum
quodlibetor

7
püf noktası, ln ve cp'nin aynı argüman sırasına sahip olduğunu hatırlamaktır - bunu 'file1'i file2 veya dir2'ye kopyalamak, ancak bir bağlantı yapmak' olarak
düşünün

Bu mantıklı, bence man sayfasında "HEDEF" kullanımı beni atar.
quodlibetor

Lütfen, nasıl köşeleri yuvarladın? Okunabilirliği geliştirdiğini hissediyorum. Kutulardaki birçok kenarın varlığında serin olmayan çirkin keskin köşeler alıyorum.
Hibou57

78

Bu konuyu araştırırken SnakeViz adlı kullanışlı bir araçla karşılaştım. SnakeViz web tabanlı bir profil görselleştirme aracıdır. Kurulumu ve kullanımı çok kolaydır. Ben her zamanki gibi bunu kullanarak bir stat dosyası oluşturmak %prunve daha sonra SnakeViz analiz yapmaktır.

Kullanılan ana viz tekniği , fonksiyon çağrıları hiyerarşisinin açısal genişliklerinde kodlanmış yaylar ve zaman bilgisi katmanları olarak düzenlendiği Sunburst şemasıdır .

En iyi şey grafikle etkileşimde bulunabilmenizdir. Örneğin, yakınlaştırmak için bir yayı tıklayabilirsiniz ve yay ve torunları daha fazla ayrıntı görüntülemek için yeni bir güneş yanığı olarak büyütülür.

resim açıklamasını buraya girin


1
CodeCabbie'nin cevabı (kısa) kurulum talimatlarını içerir ve SnakeViz'in nasıl (kolayca) kullanılacağını gösterir.
Oren Milman

İşte okudum IMHO iyi rehber nasıl jupyter dizüstü bilgisayarda Python için profil kullanmak: towardsdatascience.com/speed-up-jupyter-notebooks-20716cbe2025
Alexei Martianov

73

Her zaman nereye gittiğini bulmanın en basit ve en hızlı yolu.

1. pip install snakeviz

2. python -m cProfile -o temp.dat <PROGRAM>.py

3. snakeviz temp.dat

Tarayıcıya bir pasta grafik çizer. En büyük parça problem fonksiyonudur. Çok basit.


1
Bu çok yardımcı oldu. Teşekkür ederim.
17:14

55

Bence bu cProfileprofilleme kcachegrindiçin harika, sonuçları görselleştirmek için harika. pyprof2calltreeTutamaklar arasında dosya dönüştürme.

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

Gerekli araçları kurmak için (en azından Ubuntu'da):

apt-get install kcachegrind
pip install pyprof2calltree

Sonuç:

Sonucun ekran görüntüsü


9
Mac Kullanıcıları yüklemesi brew install qcachegrind ve her substitude kcachegrind ile qcachegrind başarılı profilleme için açıklama.
Kevin Katzke

Çalışmak için bunu yapmak zorunda kaldım:export QT_X11_NO_MITSHM=1
Yonatan Simson

41

Ayrıca kayda değer GUI cProfile döküm görüntüleyici RunSnakeRun olduğunu . Sıralamanızı ve seçmenizi sağlar, böylece programın ilgili bölümlerini yakınlaştırır. Resimdeki dikdörtgenlerin boyutları, geçen zamanla orantılıdır. Fareyi bir dikdörtgenin üzerine getirirseniz, tablodaki ve haritanın her yerindeki aramayı vurgular. Bir dikdörtgeni çift tıkladığınızda o kısmı yakınlaştırır. Size o kısmı kimin çağırdığını ve o bölümün ne dediğini gösterecektir.

Açıklayıcı bilgiler çok yardımcıdır. Yerleşik kütüphane çağrılarıyla uğraşırken size yardımcı olabilecek bu bitin kodunu gösterir. Kodu hangi dosyayı ve hangi satırı bulacağınızı söyler.

Ayrıca OP'nin 'profilleme' dediğine işaret etmek ister, ancak 'zamanlama' anlamına geldiği anlaşılmaktadır. Profillendiğinde programlar daha yavaş çalışacaktır.

resim açıklamasını buraya girin


34

Güzel bir profil oluşturma modülü line_profiler'dır (kernprof.py betiği kullanılarak çağrılır). İndirilebilir burada .

Anladığım kadarıyla, cProfile yalnızca her bir işlev için harcanan toplam süre hakkında bilgi verir. Bu nedenle, tek tek kod satırları zamanlanmaz. Bilimsel hesaplamada bu bir sorundur, çünkü çoğu zaman tek bir satır çok zaman alabilir. Ayrıca, hatırladığım gibi, cProfile numpy.dot demek için harcadığım zamanı yakalamadı.


34

Geçenlerde Python çalışma zamanı ve içe aktarma profillerini görselleştirmek için ton balığı oluşturdum ; bu burada yardımcı olabilir.

resim açıklamasını buraya girin

İle yükle

pip install tuna

Çalışma zamanı profili oluşturma

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

veya bir içe aktarma profili (Python 3.7+ gerekir)

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

Sonra sadece orkinos üzerinde dosya çalıştırın

tuna program.prof

33

Pprofil

line_profiler(burada zaten sunuldu) ayrıca şöyle ilham pprofileverdi:

Satır ayrıntı düzeyi, iş parçacığına duyarlı deterministik ve istatistikçi saf python profiler

line_profilerSaf Python olduğu için bağımsız bir komut veya modül olarak kullanılabildiği gibi satır ayrıntısı da sağlar ve hatta kolayca analiz edilebilen callgrind biçimli dosyalar oluşturabilir[k|q]cachegrind .

vprof

Ayrıca vprof , şu şekilde açıklanan bir Python paketi vardır:

[...] çalışma süresi ve bellek kullanımı gibi çeşitli Python program özellikleri için zengin ve etkileşimli görselleştirmeler sağlar.

sıcaklık haritası


14

Birçok harika yanıt var, ancak sonuçları profillemek ve / veya sıralamak için komut satırı veya harici bir program kullanıyorlar.

Komut satırına dokunmadan veya herhangi bir şey kurmadan IDE'mde (eclipse-PyDev) kullanabileceğim bir yolu gerçekten kaçırdım. İşte burada.

Komut satırı olmadan profil oluşturma

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)

Daha fazla bilgi için dokümanlara veya diğer yanıtlara bakın .


örneğin, profil {map} veya {xxx} yazdırır. {xxx} yönteminin hangi dosyadan çağrıldığını nasıl bilebilirim? benim profilim 'yöntemi' sıkıştırmak 'zlib.Compress' nesneler} yazdırır çoğu zaman alır, ama ben herhangi bir zlib kullanmıyorum, bu yüzden bazı çağrı numpy işlevi kullanabilirsiniz sanırım. Tam olarak hangi dosyanın ve satırın çok zaman aldığını nasıl bilebilirim?
machen

12

Değil beklendiği gibi çalışmaya çok dişli kodu hakkında Joe Shaw'un cevap takiben, bunu anladım runcallCprofile yöntem sadece yapıyor self.enable()ve self.disable()sadece kendiniz yapmak ve arada istersen kodu ile olabilir, böylece profilli işlev çağrısı etrafında çağrıları mevcut kodla minimum etkileşim.


3
Mükemmel ipucu! cprofile.py'Nin kaynak koduna hızlı bir bakış, tam olarak ne runcall()olduğunu gösterir. Daha spesifik olmak gerekirse, ile bir Profil örneği oluşturduktan sonra prof = cprofile.Profile()hemen arayın prof.disable()ve ardından profilli olmasını istediğiniz kod bölümünü ekleyin prof.enable()ve arayın prof.disable().
martineau

Bu çok yardımcı olur, ancak aslında etkinleştirme ve devre dışı bırakma arasındaki kodun profilli olmadığı anlaşılır - yalnızca çağırdığı işlevler. Bu hakkım var mı? Ben print_stats () sayıları herhangi birine doğru saymak için bir işlev çağrısında bu kodu sarmak gerekir.
Bob Stein

10

Virtaal'ın kaynağında , profil oluşturmayı (belirli yöntemler / işlevler için bile) çok kolaylaştıran çok kullanışlı bir sınıf ve dekoratör var. Çıktı daha sonra KCacheGrind'de çok rahat bir şekilde görüntülenebilir.


1
Bu mücevher için teşekkür ederim. Bilginize: Bu herhangi bir kod ile bağımsız bir modül olarak kullanılabilir, Virtaal kod tabanı gerekli değildir. Sadece dosyayı profiling.py dosyasına kaydedin ve profile_func () öğesini içe aktarın. Profil yapmanız ve ihlal etmeniz gereken herhangi bir işleve dekoratör olarak @profile_func () işlevini kullanın. :)
Amjith

9

cProfile hızlı profil oluşturma için harika ama çoğu zaman hatalarla benim için sona ermişti. Fonksiyon runctx, ortamı ve değişkenleri doğru bir şekilde başlatarak bu sorunu çözer, umarım birisi için yararlı olabilir:

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

7

Kümülatif bir profil oluşturmak istiyorsanız, işlevi üst üste birkaç kez çalıştırmak ve sonuçların toplamını izlemek anlamına gelir.

bu cumulative_profilerdekoratörü kullanabilirsiniz :

python> = 3.6'ya özgüdür, ancak nonlocaleski sürümlerde çalışması için kaldırabilirsiniz .

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

Misal

fonksiyonun profilini çıkarmak baz

import time

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

baz()

baz 5 kez koştu ve bunu yazdırdı:

         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}

kaç kez belirtildiğini

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

7

Tüm bu fantezi kullanıcı arayüzlerinin yüklenememesi veya çalıştırılmaması durumunda, yalnızca terminal (ve en basit) çözüm: Tamamen
yoksay cProfileve değiştir ile pyinstrument, yürütme işleminden hemen sonra çağrı ağacını toplar ve görüntüler.

Yüklemek:

$ pip install pyinstrument

Profil ve görüntü sonucu:

$ python -m pyinstrument ./prog.py

Python2 ve 3 ile çalışır.

[EDIT] Kodun yalnızca bir bölümünün profilini oluşturmak için API'nın dokümantasyonuna buradan ulaşabilirsiniz .


6

Benim yolum yappi kullanmak ( https://github.com/sumerc/yappi ). Profil oluşturma bilgilerini başlatmak, durdurmak ve yazdırmak için (örneğin bu yolla) yöntemi kaydettiğiniz (yalnızca hata ayıklama için bile) bir RPC sunucusuyla birlikte özellikle kullanışlıdır:

@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)

Daha sonra programınız çalıştığında, startProfilerRPC yöntemini çağırarak profil oluşturucuyu herhangi bir zamanda başlatabilir ve çağırarak printProfiler(veya arayan kişiye geri dönmek için rpc yöntemini değiştirerek) bir günlük dosyasına profil bilgilerini dökebilir ve bu çıktıyı alabilirsiniz:

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 

Kısa komut dosyaları için çok yararlı olmayabilir, ancak özellikle printProfilerfarklı program kullanım senaryolarını profillemek ve karşılaştırmak için yöntem zamanla birden çok kez çağrılabildiği göz önüne alındığında, sunucu tipi süreçleri optimize etmeye yardımcı olur .

Yappi'nin yeni sürümlerinde aşağıdaki kod çalışır:

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

Muazzam Yappi olarak adlandırılmamalı mı?
Therealstubot

Ne yazık ki yukarıdaki kod sadece pypy'de bulunmayan 0.62 sürümü ile çalışır. Modülün burada mevcut 0.62 kaynaktan derlenmesi gerekir: github.com/nirs/yappi/releases veya bu amaçla çatallanan repo pencereler için yaptığım yapı github.com/Girgitt/yappi/releases
Bay Girgitt

1.0 sürümü ile uyumluluk - en azından baskı çıktısı için - printProfiler işlevini değiştirerek kolayca sağlanabilir: 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)}) (Tamam verdiğim yoruma kod bloğu eklemek için birkaç kez denedikten sonra, bu program odaklı bir Soru-Cevap sitesi için inanılmaz derecede zordur. )
Bay Girgitt

4

Python'da profil oluşturma için yeni bir araç PyVmMonitor: http://www.pyvmmonitor.com/

Bazı benzersiz özelliklere sahiptir.

  • Çalışan (CPython) programa profil oluşturucu ekle
  • Yappi entegrasyonu ile isteğe bağlı profil oluşturma
  • Farklı bir makinede profil
  • Çoklu süreç desteği (çoklu işlem, django ...)
  • Canlı örnekleme / CPU görünümü (zaman aralığı seçimi ile)
  • CProfile / profile entegrasyonu ile deterministik profil oluşturma
  • Mevcut PStat sonuçlarını analiz edin
  • DOT dosyalarını açma
  • Programlı API erişimi
  • Örnekleri yöntem veya hatta göre gruplandırma
  • PyDev entegrasyonu
  • PyCharm entegrasyonu

Not: Ticari, ancak açık kaynak için ücretsiz.


4

gprof2dot_magic

gprof2dotHerhangi bir Python deyimini JupyterLab veya Jupyter Notebook'da DOT grafiği olarak profilleştirmek için sihirli işlev .

resim açıklamasını buraya girin

GitHub repo: https://github.com/mattijn/gprof2dot_magic

Kurulum

Python paketinizin olduğundan emin olun gprof2dot_magic.

pip install gprof2dot_magic

Bağımlılıkları gprof2dotve graphvizaynı zamanda kurulacak

kullanım

Sihirli işlevi etkinleştirmek için önce gprof2dot_magicmodülü yükleyin

%load_ext gprof2dot_magic

ve daha sonra herhangi bir satır ifadesini DOT grafiği olarak profil yapın:

%gprof2dot print('hello world')

resim açıklamasını buraya girin


3

Hiç python betiğinin ne yaptığını bilmek istediniz mi? İnceleme Kabuğuna girin. Inspect Shell, çalışan komut dosyasını kesmeden globalleri yazdırmanıza / değiştirmenize ve işlevleri çalıştırmanıza olanak tanır. Şimdi otomatik tamamlama ve komut geçmişi ile (sadece linux'da).

Inspect Shell, pdb tarzı bir hata ayıklayıcı değil.

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

Bunu (ve kol saatinizi) kullanabilirsiniz.


3

Https://stackoverflow.com/a/582337/1070617 adresine eklemek için ,

CProfile kullanmanıza ve çıktısını kolayca görüntülemenize izin veren bu modülü yazdım. Daha fazla bilgi için: https://github.com/ymichael/cprofilev

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

Ayrıca , toplanan istatistiklerin nasıl anlaşılacağı hakkında http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html adresine bakın .


3

Profillemeden ne görmek istediğinize bağlı olacaktır. Basit zaman metrikleri (bash) ile verilebilir.

time python python_prog.py

'/ Usr / bin / time' bile '--verbose' işaretini kullanarak ayrıntılı metrikler verebilir.

Her bir işlev tarafından verilen zaman metriklerini kontrol etmek ve işlevler için ne kadar zaman harcandığını daha iyi anlamak için, python'da dahili cProfile'ı kullanabilirsiniz.

Performans gibi daha ayrıntılı metriklere girmek, zamanın tek metriği değildir. Bellek, iş parçacıkları vb. Hakkında endişe duyabilirsiniz .
Profil oluşturma seçenekleri:
1. line_profiler , zamanlama metriklerini satır satır bulmak için yaygın olarak kullanılan başka bir profil oluşturucudur.
2. memory_profiler bellek kullanımını profillendiren bir araçtır.
3. heapy (Guppy projesinden) nesnelerin nasıl kullanıldığını görüntüleyin.

Bunlar benim kullanma eğilimim olan yaygın olanlardan. Ama daha fazla bilgi edinmek istiyorsanız, bu kitabı okumaya çalışın . Cython ve JIT (Tam zamanında) derlenmiş python kullanımı ile ilgili gelişmiş konulara geçebilirsiniz.


2

Austin gibi istatistiksel bir profil oluşturucuyla , hiçbir enstrümantasyon gerekmez, yani sadece Python uygulamasından profil oluşturma verilerini alabilirsiniz

austin python3 my_script.py

Ham çıktı çok yararlı değildir, ancak size (gerçek zamanın mikrosaniye cinsinden ölçülen) zamanın nerede harcandığını gösteren bir alev grafiği temsili elde etmek için bunu flamegraph.pl'ye bağlayabilirsiniz .

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

1

Ayrıca, statprof . Bu bir örnekleme profilidir, bu nedenle kodunuza minimum ek yük ekler ve satır tabanlı (yalnızca işlev tabanlı değil) zamanlamalar verir. Oyunlar gibi gerçek zamanlı yumuşak uygulamalar için daha uygundur, ancak cProfile'dan daha az hassas olabilir.

Pypi sürüm öylesine ile yükleyebilirsiniz, biraz eski pipbelirterek git depo :

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

Bu şekilde çalıştırabilirsiniz:

import statprof

with statprof.profile():
    my_questionable_function()

Ayrıca bkz. Https://stackoverflow.com/a/10333592/320036


1

Ben sadece pypref_time esinlenerek kendi profiler geliştirdi:

https://github.com/modaresimr/auto_profiler

Bir dekoratör ekleyerek zaman alıcı işlevler ağacını gösterecektir

@Profiler(depth=4, on_disable=show)

Install by: pip install auto_profiler

Misal

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()

Örnek Çıktı


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]

1

Bir IPython not defterinde kod snippet'leriniz için hızlı profil istatistikleri almak için. Bir line_profiler ve memory_profiler doğrudan not defterlerine gömülebilir.

Anla!

!pip install line_profiler
!pip install memory_profiler

Yükle!

%load_ext line_profiler
%load_ext memory_profiler

Kullanın!


% süresi

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

verir:

  • CPU süreleri: CPU seviyesi yürütme süresi
  • sys süreleri: sistem düzeyinde yürütme süresi
  • toplam: CPU zamanı + sistem zamanı
  • Duvar zamanı: Duvar Saati Zamanı

% sürümüyle gelen timeit

%timeit -r 7 -n 1000 print('Outputs execution time of the snippet') 
#1000 loops, best of 7: 7.46 ns per loop
  • Döngü (n) kez verilen sayıda çalışmadan (r) en iyi zamanı verir.
  • Sistem önbelleğe almayla ilgili ayrıntılar:
    • Kod parçacıkları birden çok kez yürütüldüğünde, sistem birkaç işlemi önbelleğe alır ve profil raporlarının doğruluğunu engelleyebilecek bir daha yürütmez.

% prun

%prun -s cumulative 'Code to profile' 

verir:

  • işlev çağrısı sayısı (ncalls)
  • işlev çağrısı başına giriş var (farklı)
  • arama başına geçen süre (arama başına)
  • bu işlev çağrısına kadar geçen süre (cumtime)
  • vb. olarak adlandırılan işlev / modülün adı ...

Birikimli profil


% memit

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

verir:

  • Hafıza kullanımı

% lprun

#Example function
def fun():
  for i in range(10):
    print(i)

#Usage: %lprun <name_of_the_function> function
%lprun -f fun fun()

verir:

  • Line wise istatistikleri

LineProfile


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.