2014-11-30 59 views
7

Açık kaynaklı bir C++ uygulamasına katkıda bulunuyorum. Bu uygulamada böyleloglama performansı ve operatör <<

if (Debug) std::cout << "MyClass | my debug message" << MyExpensiveStringConvertion() << std::endl; 

olarak çizgilerle yapılan tüm günlük Ben öyle ki otomatik biçimlendirme ne yaparsa boost easylogginppp, gibi mevcut çerçevelerin birini kullanarak önerdi (diğer dillerde) daha gelişmiş günlüğü çerçevesini kullanmak için kullanılıyor ise ve çalışma zamanında yapılandırılabilir.

ama "(ayıklama) eğer" neredeyse hiçbir yüke sahiptir kullanarak yazma sırasında

Log(debug) << "MyClass | my debug message" << MyExpensiveStringConvertion() 

< < operatör ve MyExpensiveStringConvertion() olay günlüğü hesaplanması hem gerektirir yanıtını verdi devre dışıdır. Bu bağımsız değişken doğru mu? eğer doğruysa, önemsemeliyiz? Çoğu oturum açma çerçevesi bu şekilde çalışır gibi gözüküyor, çoğu geliştiricinin dikkat etmemesi çoğu

Güncelleme: Anladığım (Hata Ayıkla) formunun sadece basit bir bool testi gerektirip gerektirmediğini anlıyorum, ancak maliyetlerin düşürülmesi için her türlü hileyi uygulamak için kayıt çerçevelerini beklemekteydim. "#define LOG (level) düzeyinde ise (doDebug (level)) Log (level)" diyen Dietmar Kühl.

+3

MyExpensiveStringConver [s] ion() 'un daha fazla olması gerektiği doğrudur. '<<' değerlendirmesinden daha iyi. – Ryan

+1

Çoğu günlük çerçevesi çöp. Bu yüzden kendi kitabımı yazdım. – doc

+0

@doc Me de, üretimde can sıkıcı problemlerle karşılaşmamıza rağmen, uygun bir çerçevenin halihazırda ele alınmış olması muhtemeldir (örneğin, bir kişi işlemi klonladıktan ve günlük dosyamda yetim bir tanıtıcı bıraktığından, günlüğe kaydetme başarısız oluyor) –

cevap

0

Teşekkür temsil etmek anlamına gelmez.

(ayıklama) daha verimli görünüyor ama çoğu günlük çerçeve onlar aslında diğer posterleri vardır ++ easylogging Örneğin

tarafından mentionnned hile dahil olacak şekilde uygulanacak görünüyor eğer hem uygulanmaktadır DLOG ve DCLOG #define DCLOG (LEVEL, ...) if (_ELPP_DEBUG_LOG) tıkayabilir (LEVEL, VA_ARGS)

ve Glôg (google günlüğü) olarak da ayrıca ya bir küresel değişkeni denetler veya devre dışı bırakılabilir bir DLOG vardır Derleme zamanı. Glog doc ayrıca "" " diyor. Glog tarafından sağlanan koşullu günlüğe kaydetme makroları (örn. CHECK, LOG_IF, VLOG, ...) dikkatlice uygulanır ve koşullar yanlış olduğunda sağ taraftaki ifadeleri yürütmez. , aşağıdaki onay uygulamanızın performansını feda olmayabilir

Slayt (obj.ok) < < obj.CreatePrettyFormattedStringButVerySlow();. """

ben artırmak günlüğü de benzer performans hileler

uygular tahmin
4

Çıkış işleminin önünde koşullu olmayan temel sorun, tüm bağımsız değişkenlerin değerlendirilmekte olmasıdır. Gerçek çıkış işlemlerini kısa devre yapmak kolaydır (yalnızca Log(debug)'un kendi durumunda ayarlanmış olan std::ios_base::failbit ile bir akış döndürdüğünden emin olun), ancak tüm argümanları değerlendirmek, günlüğe kaydetme sırasında harcamak istemediğiniz bir yükü dahil etme eğilimindedir. Tabii ki,

#define LOG(level) if (doDebug(level)) Log(level) 

gibi bir şey kullanarak günlük için gösterim düzeltmek ... ve siz uygulama ilk seçenek olacak sonra günlük büyük miktarda kullanmak bekliyorsanız o zaman

LOG(debug) << "MyClass | my debug message" << MyExpensiveStringConversion(); 
+0

fikir, ama ben çoğu logger çerçevelerinde kutudan çıkmanın bir tür performans hilesi olması bekleniyordu, değil mi? –

1

kullanmak (büyük) bir fark yaratır.
Aksi takdirde, gerçekten önemli değil.

Günlük işlevini makroda sarmalayabilir, böylece karşılaştırma amacıyla zaman için derleme sırasında kolayca devre dışı bırakabilirsiniz. doğrudur

#ifdef LOG_ENABLED 
    #define LOGSTR(x) do { \ 
        debug && Log(debug) << x << MyExpensiveStringConvertion() \ 
     } while (0) 
#else 
    #define LOGSTR(x) (void)0 
#endif 
+1

'# else' dalında' #define LOGSTR (x) (void) 0' tanımlamak daha iyidir. Aksi takdirde bunun gibi bir kod "eğer (bir şey) LOGSTR" ("blahblah"); 'önceden kestirilemez (çoğu durumda derleme hatası verir). Yine de +1. – doc

+0

@doc 'do {} (0)' en güçlü yoldur, [buraya bakın] (http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-cc -macros) –

+0

Yararlı yorumlara göre düzeltildi. – egur

1

. Boolean değerine (if (Debug)) karşı basit bir test ucuzdur ve nitelenmemiş Log(debug) ifadesinin gerektirdiği pahalı "Convertion" dizisini atlar. Her çoklu aramalar bakıyoruz

call ExpensiveStringConversion 
call operator << with result (maybe, depends on what class is returned by conversion) 
call operator << for whatever class Log(debug) evaluates to (with test for debug in callee) 
clean up after function call 
carry on... 

(aslında, bu LR ilişkisel biraz basitleştirilmiş ve operator<< çağrı olarak tamamen doğru değildir olduğunu)

:

test some_register, Debug 
jne skip_the_debug_crap 
-- potentially lots of code here -- 

skip_the_debug_crap: 
carry on... 

Karşı: Kod esasen tutarındaki Zaman, bazı pahalı, sonuçta hiç kaydedilmemeli veya olmasın. Ayrıca, Log(debug) ve ExpensiveStringConversion, noexcept değilse, potansiyel yığın açma işlemi için bazı ek ek yükler gerekli olacaktır.

Derleme zamanı makroları kullanarak önerilen çözümler, yapılandırma yapılandırması için başlatma veya çalışma zamanı değişiklikleri anlamına gelmez.Düzenlendiğinde

: sözde montaj benzeri damıtma (test, JnE, çağrı) x86 mimarisini ben kendi soruya yanıt verebileceğinizi biliyor am tüm posterlerine

İlgili konular