2010-08-25 29 views
10

Bir web.py web arabirimi sağlamak için jeneratörlerin sonuçlarını yoğun şekilde kullanan bir uygulamayı uyarlıyorum.Python jeneratörü Profilleme

Şimdiye kadar, çağrıyı döngü içi ve çıktı üreten deyimlere bir işlevde sarmalı ve bunu cProfile.run() veya runctx() kullanarak arayabilirim. Kavramsal olarak:

web.py olarak
def output(): 
    for value in generator(): 
     print(value) 

cProfile.run('output()') 

hemen yield kullanılarak her iterasyon adımında Uzun çalışabilecek hesaplama çıktı üretmek istiyorum çünkü, ben, bunu şu şekilde kaydırmak zorunda:

class index: 
    def GET(self): 
     for value in generator(): 
      yield make_pretty_html(value) 

İkinci örnekte kullanıldığı zaman ilk örnekte olduğu gibi jeneratöre yapılan tüm aramaları izlemenin bir yolu var mı?

+0

Sadece tek bir iterasyon yerine tüm işlev çağrısını ölçmek mi istiyorsunuz? CProfile.run ('liste (dizin(). GET())') 'de olduğu gibi? –

+0

Özünde, bu for-döngüsünün başardığı şeydir. Buradaki problem, 'GET()' e yapılan aramalar üzerinde hiçbir kontrolüm olmaması, 'web.py' tarafından ele alındığıdır. Dahası, çıktının artık bu şekilde üretileceğini düşünmüyorum (dönüş değerini kullanarak). –

cevap

5

kullanmak. here aracılığıyla profillemenin dönüş değeri.

import cProfile 
import pstats 
import glob 
import math 

def gen(): 
    for i in range(1, 10): 
     yield math.factorial(i) 

class index(object): 
    def GET(self): 
     p = cProfile.Profile() 

     it = gen() 
     while True: 
      try: 
       nxt = p.runcall(next, it) 
      except StopIteration: 
       break 
      print nxt 

     p.print_stats() 

index().GET() 

Ben de birden böyle profilleme sonuçlarını birleştirebilir documentation ve mağaza aracılığıyla (Ben eşsiz dosya adları vererek başladığınızda)/kombine bunları analiz.

0

İlgilendiğiniz parçaları izlemek için time.time() yöntemini kullanabilir misiniz? Sadece şimdiki zamanı al ve son ölçümden çıkar çık.

+0

Zaten toplam zamanlamayı aldım, ancak "İşlem 5.382 saniye sürdü" performans darboğazlarını bulmak için yeterince spesifik değil. Oldukça geniş ve dallanmış bir jeneratörler zincirini dahili olarak kullanıyorum ve daha sonra analiz için kullanıcı girdisini ve sonuçtaki performansı saklamayı amaçlıyorum. Her aramada ortalama 0.000 saniye süren ancak on binlerce kez çağrılabilen birkaç fonksiyon var. –

+0

Bu durumda, bu işlevlerin her yürütülmesi için bir tamsayı sayacınız olabilir ve yalnızca her 1000'er yürütmede bir ölçüm yapabilirsiniz? Bunun yerine kod parçalarını ölçebilir ve darboğazları daraltabilirsiniz. Kodlara bağlı olarak biraz sıkıcı olabileceğini anlıyorum. – karpathy

1

Jeneratördeki her bir aramayı 'sonraki' olarak profillemeye çalıştığınız anlaşılıyor. Eğer öyleyse, jeneratörü bir profil jeneratörüne sarabilirsiniz. Yorumlanan bölümün, sonuçları bir günlük dosyasına veya veritabanına göndereceği böyle bir şey.

 
def iter_profiler(itr): 
    itr = iter(itr) 
    while True: 
    try: 
     start = time.time() 
     value = itr.next() 
     end = time.time() 
    except StopIteration: 
     break 
    # do something with (end - stop) times here 
    yield value 
 

Sonra yerine generator() olarak jeneratör nesnelleştirilme sen nihayet bir çözüm buldum iter_profiler(generator())

+1

alternatif olarak, jeneratörün tanımında değiştirilmiş bir sürümünü bir dekoratör olarak uygulayabilirsiniz. – aaronasterling

+0

Temel olarak haklısınız. Zaten orjinal yazımın ikinci örneğindeki 'for' döngüsünden önce ve sonra arasındaki milisaniye sayıyorum, bu yüzden zaten bu bilgilere sahibim (her ne kadar biraz daha fazla olsa da, birkaç milis önemli değil). Bununla birlikte, kodumdaki "sıcak noktalar" ın (düzinelerce zamanın ölümü ne zaman gerçekleşir?), Onlarca sonucun diğerlerinden daha uzun sürdüğünden daha fazla önemsiyorum. Bu nedenle, bir "profile/cProfile" tabanlı çözüm (sonuç başına bir rapor oluşturmaz) umuyordum. Profiler raporlarını birleştirmenin bir yolu varsa, bu gitmek için bir yol olurdu. –

İlgili konular