2010-04-12 17 views
5

के लिए प्रदर्शन ट्रिक्स मैं सी # लॉगिंग में देख रहा हूं और मैं नहीं चाहता कि संदेश लॉगिंग थ्रेसहोल्ड से नीचे है तो मेरे लॉग संदेश किसी भी समय प्रसंस्करण करने के लिए खर्च करें। लॉग पैरामीटर का मूल्यांकन करने के बाद लॉग 4नेट सबसे अच्छा मैं थ्रेसहोल्ड चेक देख सकता हूं।सी # लॉगिंग

उदाहरण:

_logger.Debug("My complicated log message " + thisFunctionTakesALongTime() + " will take a long time") 

यहां तक ​​कि अगर सीमा डीबग से ऊपर है, thisFunctionTakesALongTime अभी भी मूल्यांकन किया जाएगा।

log4net में आप _logger.isDebugEnabled उपयोग करें ताकि आप के साथ

if(_logger.isDebugEnabled) 
    _logger.Debug("Much faster") 

मैं अगर वहाँ .net प्रवेश के लिए एक बेहतर समाधान है कि एक जांच हर बार मैं चाहता हूँ को शामिल नहीं करता है जानना चाहता हूँ अंत अपेक्षा की जाती है दर्ज करना।

C++ में मैं अपने LOG_DEBUG मैक्रो लॉग स्तर ही जाँच करता है के बाद से

LOG_DEBUG("My complicated log message " + thisFunctionTakesALongTime() + " will take no time") 

करने की अनुमति दी है। यह मुझे अपने ऐप में एक 1 लाइन लॉग संदेश रखने के लिए स्वतंत्र करता है जिसे मैं बहुत पसंद करता हूं। किसी को इस व्यवहार को सी # में दोहराने का तरीका पता है?

उत्तर

8

आप .NET 3.5 (सी # 3.0) लक्षित कर सकते हैं, तो आप उपयोग कर सकते हैं extension methodsif बयान रैप करने के लिए। एक पूर्वप्रक्रमक आप एसओएल रहे बिना

public class Log4NetExtensionMethods { 
    // simple string wrapper 
    public void Log_Debug(this log4net.ILog logger, string logMessage) { 
     if(logger.isDebugEnabled) { 
      logger.Debug(logMessage); 
     } 
    } 

    // this takes a delegate so you can delay execution 
    // of a function call until you've determined it's necessary 
    public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) { 
     if(logger.isDebugEnabled) { 
      logger.Debug(logMessageDelegate()); 
     } 
    } 
} 
+0

लेकिन अगर मैं लॉग संदेश प्राप्त करने के लिए कार्यों का मूल्यांकन कर रहा हूं, तो क्या यह धीमा नहीं होगा? यदि लॉग स्तर मेरी दहलीज से नीचे है तो मैं सभी फ़ंक्शन मूल्यांकन से बचना चाहता हूं। – Charles

+1

आप सही हैं कि आपको फ़ंक्शन मूल्यांकन में देरी करने की आवश्यकता होगी।मेरा अद्यतन देखें जो एक अज्ञात प्रतिनिधि का उपयोग करता है। –

+1

डी ओह, यह मेरा जवाब भी था। मुझे आपको चेतावनी दी जानी चाहिए कि यदि आप गति की तलाश में हैं, तो आप प्रतिनिधियों का उपयोग नहीं करना चाहते हैं। आपको केवल हिट लेना चाहिए और अगर किसी भी कीमत के आसपास 'if (logger.isDebugEnabled)' का उपयोग करना चाहिए। कोई समाधान नहीं है जो प्रदर्शन और सुरुचिपूर्ण दोनों है। – bobbymcr

-2

: इस विधि में जांच लपेटकर द्वारा

logger.Log_Debug("Much faster"); 

logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" }); 

:

तो आप बराबर "मैक्रो" कर सकते हैं। निश्चित रूप से सी # कंपाइलर को आपके कोड को खिलाने से पहले आपको किसी एक का उपयोग करने से रोकने में कुछ भी नहीं है।

+0

अज्ञात प्रतिनिधि और अतिरिक्त कक्षाएं - वाह जो बहुत अधिक टाइपिंग है। – blammo

1

समस्या यह है कि विधि लागू होने से पहले सभी विधि मानकों का मूल्यांकन किया जाना चाहिए। आपके द्वारा उपयोग किए जा रहे सिंटैक्स को देखते हुए इसके चारों ओर कोई रास्ता नहीं है। चूंकि सी # में वास्तविक प्रीप्रोसेसर या मैक्रोज़ नहीं हैं, इसलिए आप "LOG_DEBUG" जैसी कुछ भी नहीं कर सकते हैं। सुझाव दिया गया है कि आप सबसे अच्छा कर सकते हैं if (logger.isDebugEnable) का उपयोग करें।

एकमात्र चीज जिसे मैं सोच सकता हूं शायद मूल्यांकन में देरी के लिए लैम्ब्डा अभिव्यक्ति की तरह कुछ उपयोग कर रहा है। लेकिन मैं आपको चेतावनी दूंगा कि यह निश्चित रूप से के अंत में एक प्रदर्शन हिट होगा।

internal class Sample 
{ 
    private static void Main(string[] args) 
    { 
     DelayedEvaluationLogger.Debug(logger,() => "This is " + Expensive() + " to log."); 
    } 

    private static string Expensive() 
    { 
     // ... 
    } 
} 

internal static class DelayedEvaluationLogger 
{ 
    public static void Debug(ILog logger, Func<string> logString) 
    { 
     if (logger.isDebugEnabled) 
     { 
      logger.Debug(logString()); 
     } 
    } 
} 
+0

क्या लैम्ब्डा अभिव्यक्ति महंगे हैं? – Charles

+2

@ चार्ल्स: लैम्बडास अपेक्षाकृत सस्ती हैं जहां तक ​​देर से बाध्यकारी हो जाता है, लेकिन बुलियन चेक और विधि कॉल से कहीं अधिक महंगा है। एक अरब पुनरावृत्तियों (यहां कोड: http://pastebin.com/aRtMtsxz) पर मेरे सरल परीक्षण में, लॉगिंग सक्षम नहीं होने पर मैंने लैम्ब्डा बनाम बूलियन चेक के लिए लगभग 25% ओवरहेड मापा। एक कैश्ड लैम्ब्डा के साथ (लैम्ब्डा को एक फ़ील्ड में सेव करें ताकि यह हर बार फिर से उत्पन्न न हो), थोड़ा कम ओवरहेड (20% से कम कूड़े) होता है। – bobbymcr

2

17.4.2 सशर्त विशेषता

विशेषता सशर्त सशर्त तरीकों की परिभाषा सक्षम बनाता है। सशर्त विशेषता एक सशर्त संकलन प्रतीक का परीक्षण करके एक शर्त इंगित करता है। किसी सशर्त विधि को कॉल या तो कॉल के बिंदु पर परिभाषित किया गया है या नहीं, इस पर निर्भर करता है या नहीं। यदि प्रतीक परिभाषित किया गया है, तो कॉल शामिल है; अन्यथा, कॉल (कॉल के पैरामीटर के मूल्यांकन सहित) छोड़ा जाता है।

[ Conditional("DEBUG") ] 
public static void LogLine(string msg,string detail) 
{ 
    Console.WriteLine("Log: {0} = {1}",msg,detail); 
} 

public static void Main(string[] args) 
{ 
    int Total = 0; 
    for(int Lp = 1; Lp < 10; Lp++) 
    { 
     LogLine("Total",Total.ToString()); 
     Total = Total + Lp; 
    } 
} 
+0

यह दिलचस्प है, मैं इसके बारे में कुछ और शोध करूंगा। एमएसडीएन: http://msdn.microsoft.com/en-us/library/aa664622%28VS.71%29.aspx – Charles

+1

मुझे लगता है कि बेहतर लॉगिंग लाइब्रेरी पहले से ही इस तकनीक का उपयोग करती है। – blammo

+1

सिर्फ इसलिए कि आप "logger.debug" विधि को कॉल कर रहे हैं इसका मतलब यह नहीं है कि आप वास्तव में डीबग मोड में चल रहे हैं। नाम "डेवलपर" द्वारा परिभाषित अनुसार "डीबग" नाम वास्तव में केवल मनमाने ढंग से थ्रेसहोल्ड के लिए विधि का नाम है। मुझे आश्चर्य होगा अगर Log4Net, EnterpriseLibrary, आदि ... वास्तव में किसी भी सशर्त विशेषताओं का उपयोग करते हैं क्योंकि विशेषता संकलन प्रतीक की उपस्थिति पर निर्भर करती है। –

संबंधित मुद्दे