2010-12-20 20 views
9

Diğer işlevleri çağıran bir işlevi görüntülemeye çalışıyorum.Daha fazla işlev rapor etmek için Python'da cProfiler derinliğini arttırmak?

from mymodule import foo 
def start(): 
    # ... 
    foo() 

import cProfile as profile 
profile.run('start()', output_file) 
p = pstats.Stats(output_file) 
print "name: " 
print p.sort_stats('name') 
print "all stats: " 
p.print_stats() 
print "cumulative (top 10): " 
p.sort_stats('cumulative').print_stats(10) 

Ben profilci her zaman yerine hangi çağrıları) (alt fonksiyonlar foo içine aşağı brekaing arasında MyModule ait ") (foo" fonksiyonu harcama diyor bulmak şu şekildedir: Ben profilcisini diyoruz ne görmek istersem Profilcinin bu işlevlerin performansını nasıl rapor edebilirim?

Teşekkürler.

+1

Başarısız olduğunu gösteren tekrarlanabilir bir örnek eklemeniz gerekir. –

cevap

-1

Belki de benzer bir sorunla karşı karşıyasınız, bu yüzden burada sorunumu açıklayacağım. Benim profil kod şuna benziyordu:

def foobar(): 
    import cProfile 
    pr = cProfile.Profile() 
    pr.enable() 
    for event in reader.events(): 
     baz() 
     # and other things 

    pr.disable() 
    pr.dump_stats('result.prof') 

Ve son profilleme çıkışı sadece events() çağrıyı içeriyordu. Boş döngü profillemem olduğunu fark etmek için çok az zaman harcadım. Elbette, bir müşteri kodundan birden fazla foobar() çağrısı vardı, ancak boş bir döngü ile son bir çağrıya anlamlı profilleme sonuçları yazılmıştır.

0

Yöntem çağrılarının hiyerarşik bir şekilde bozulmasını almak için p.print_callees() gerekir. Çıktı oldukça açıklayıcı: Sol sütunda ilgi fonksiyonunuzu bulabilirsiniz. foo(), daha sonra sağ taraftaki sütuna giden tüm çağrılan alt işlevler ve kapsamları toplam ve kümülatif zamanlarını gösterir. Bu alt aramalar için arızalar da dahildir.

-1

İlk olarak, Asker'ın sorununu çoğaltamayacağımı söylemek istiyorum. Profiler (py2.7'de) kesinlikle çağrılan işlevlere ve yöntemlere iner. (Py3.6 için dokümanlar aynı görünmekle birlikte, py3 üzerinde test yapmadım.) Tahminimce, kümülatif zamana göre sıralanan ilk 10 getiriye sınırlanmasıyla, bunların ilk N'si çok yüksek seviyeli fonksiyonlardı. minimum zaman ve foo() tarafından çağrılan fonksiyonlar listenin altından düştü.

Test için bazı büyük sayılarla oynamaya karar verdim.

# file: mymodule.py 
import math 

def foo(n = 5): 
    for i in xrange(1,n): 
     baz(i) 
     bar(i ** i) 

def bar(n): 
    for i in xrange(1,n): 
     e = exp200(i) 
     print "len e: ", len("{}".format(e)) 

def exp200(n): 
    result = 1 
    for i in xrange(200): 
     result *= n 
    return result 

def baz(n): 
    print "{}".format(n) 

Ve (Asker en çok benzer) dahil dosyası::

# file: test.py 

from mymodule import foo 

def start(): 
    # ... 
    foo(8) 

OUTPUT_FILE = 'test.profile_info' 

import pstats 
import cProfile as profile 

profile.run('start()', OUTPUT_FILE) 
p = pstats.Stats(OUTPUT_FILE) 
print "name: " 
print p.sort_stats('name') 
print "all stats: " 
p.print_stats() 
print "cumulative (top 10): " 
p.sort_stats('cumulative').print_stats(10) 
print "time (top 10): " 
p.sort_stats('time').print_stats(10) 

Bildirim son satırı İşte benim test kod. "excluding time made in calls to sub-functions" işlevinde harcanan toplam süre olan time tarafından sıralanmış bir görünüm ekledim. Bu görünümü çok daha faydalı buluyorum, çünkü gerçek iş yapan işlevleri destekleme eğilimindedir ve optimizasyona ihtiyaç duyabilir.

cumulative (top 10): 
Thu Mar 24 21:26:32 2016 test.profile_info 

     2620840 function calls in 76.039 seconds 

    Ordered by: cumulative time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 76.039 76.039 <string>:1(<module>) 
     1 0.000 0.000 76.039 76.039 test.py:5(start) 
     1 0.000 0.000 76.039 76.039 /Users/jhazen/mymodule.py:4(foo) 
     7 10.784 1.541 76.039 10.863 /Users/jhazen/mymodule.py:10(bar) 
    873605 49.503 0.000 49.503 0.000 /Users/jhazen/mymodule.py:15(exp200) 
    873612 15.634 0.000 15.634 0.000 {method 'format' of 'str' objects} 
    873605 0.118 0.000 0.118 0.000 {len} 
     7 0.000 0.000 0.000 0.000 /Users/jhazen/mymodule.py:21(baz) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 

bu ekranda üst 3 işlevleri yalnızca bir kez çağrıldı Bakın nasıl:

İşte Asker (-sorted cumulative) den çalıştığını sonuçlarının bir parçası. en time -sorted görünüm bakalım:

time (top 10): 
Thu Mar 24 21:26:32 2016 test.profile_info 

     2620840 function calls in 76.039 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
    873605 49.503 0.000 49.503 0.000 /Users/jhazen/mymodule.py:15(exp200) 
    873612 15.634 0.000 15.634 0.000 {method 'format' of 'str' objects} 
     7 10.784 1.541 76.039 10.863 /Users/jhazen/mymodule.py:10(bar) 
    873605 0.118 0.000 0.118 0.000 {len} 
     7 0.000 0.000 0.000 0.000 /Users/jhazen/mymodule.py:21(baz) 
     1 0.000 0.000 76.039 76.039 /Users/jhazen/mymodule.py:4(foo) 
     1 0.000 0.000 76.039 76.039 test.py:5(start) 
     1 0.000 0.000 76.039 76.039 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 

Şimdi numaralı giriş mantıklı. Tekrarlanan çarpma ile 200. güce bir şey yükseltmek, "naif" bir stratejidir.en değiştirin edelim:

def exp200(n): 
    return n ** 200 

Ve sonuç: zamanında güzel bir gelişme

time (top 10): 
Thu Mar 24 21:32:18 2016 test.profile_info 

     2620840 function calls in 30.646 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
    873612 15.722 0.000 15.722 0.000 {method 'format' of 'str' objects} 
     7 9.760 1.394 30.646 4.378 /Users/jhazen/mymodule.py:10(bar) 
    873605 5.056 0.000 5.056 0.000 /Users/jhazen/mymodule.py:15(exp200) 
    873605 0.108 0.000 0.108 0.000 {len} 
     7 0.000 0.000 0.000 0.000 /Users/jhazen/mymodule.py:18(baz) 
     1 0.000 0.000 30.646 30.646 /Users/jhazen/mymodule.py:4(foo) 
     1 0.000 0.000 30.646 30.646 test.py:5(start) 
     1 0.000 0.000 30.646 30.646 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 

. Şimdi str.format() bizim en kötü suçlu. İlk denemem (sadece numarayı hesaplamak ve onunla hiçbir şey yapmamak) çünkü bu sayının uzunluğunu yazdırmak için bar() satırını ekledim, bu sayede en iyi duruma getirilmiştim ve bunu engelleme girişimi (gerçekten çok hızlı olan numarayı basma)) G/Ç'de engelleniyormuş gibi görünüyordu, dolayısıyla sayının uzunluğunu yazdırmaktan ödün verdim. Hey, bu taban-10 kaydı. en deneyelim:

def bar(n): 
    for i in xrange(1,n): 
     e = exp200(i) 
     print "log e: ", math.log10(e) 

Ve sonuç:

time (top 10): 
Thu Mar 24 21:40:16 2016 test.profile_info 

     1747235 function calls in 11.279 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     7 6.082 0.869 11.279 1.611 /Users/jhazen/mymodule.py:10(bar) 
    873605 4.996 0.000 4.996 0.000 /Users/jhazen/mymodule.py:15(exp200) 
    873605 0.201 0.000 0.201 0.000 {math.log10} 
     7 0.000 0.000 0.000 0.000 /Users/jhazen/mymodule.py:18(baz) 
     1 0.000 0.000 11.279 11.279 /Users/jhazen/mymodule.py:4(foo) 
     7 0.000 0.000 0.000 0.000 {method 'format' of 'str' objects} 
     1 0.000 0.000 11.279 11.279 test.py:5(start) 
     1 0.000 0.000 11.279 11.279 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 

Hmm, hatta str.format() olmadan bar() harcanan zamanın hala adil bir miktar.

time (top 10): 
Thu Mar 24 21:45:24 2016 test.profile_info 

     1747235 function calls in 5.031 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
    873605 4.487 0.000 4.487 0.000 /Users/jhazen/mymodule.py:17(exp200) 
     7 0.440 0.063 5.031 0.719 /Users/jhazen/mymodule.py:10(bar) 
    873605 0.104 0.000 0.104 0.000 {math.log10} 
     7 0.000 0.000 0.000 0.000 /Users/jhazen/mymodule.py:20(baz) 
     1 0.000 0.000 5.031 5.031 /Users/jhazen/mymodule.py:4(foo) 
     7 0.000 0.000 0.000 0.000 {method 'format' of 'str' objects} 
     1 0.000 0.000 5.031 5.031 test.py:5(start) 
     1 0.000 0.000 5.031 5.031 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 

Şimdi işlek işlevini fiili çalışma yapıyor şeyler gibi görünüyor, bu yüzden biz optimize tamamladıktan düşünüyorum:

def bar(n): 
    z = 0 
    for i in xrange(1,n): 
     e = exp200(i) 
     z += math.log10(e) 
    return z 

Ve sonuç: en o baskı kurtulmak edelim.

Bu yardımcı olur umarım!

İlgili konular