क्या मुझे आवेदन से पहले NSLog को निष्क्रिय करना होगा?


117

IPhone के लिए एक ऐप जारी करते समय, अगर मैं अक्षम करता हूं तो NSLog();यह बेहतर प्रदर्शन करेगा?


1
अपने वर्तमान प्रोजेक्ट में मैं UALogger का उपयोग करता हूं । यह उत्पादन में लॉग इन नहीं करता है , यदि आप इसे स्पष्ट रूप से नहीं पूछते हैं। और सादे NSLog पर अन्य लाभ हैं जैसे कि गंभीरता का स्तर ( DEBUG , INFO और आदि के साथ) आउट ऑफ बॉक्स। बहुत बढ़िया!
एंटोन गेनको

1
अपने प्रश्न का उत्तर देने के लिए "क्या यह बेहतर प्रदर्शन करेगा?" हाँ, यह करता है, लेकिन आपको जो उपज मिलती है वह इस बात पर निर्भर करती है कि NSLog()आपके ऐप में कितने हैं। NSLog()निष्पादित करने में समय लगता है और आपके ऐप के रनटाइम में अतिरिक्त ओवरहेड जोड़ता है। वैसे भी, अगर यह एक सरल DEBUG प्रीप्रोसेसर मैक्रो के साथ प्रदर्शन में मदद करता है, तो हमें इसे अक्षम करना चाहिए।
स्कॉट

मैं यह भी सुझाव देता हूं कि यदि आपके पास अपने कोड में बहुत सारे NSLog / प्रिंट स्टेटमेंट हैं, तो यह सुझाव दे सकता है कि आपको डिबगर के बारे में अधिक सीखने में कुछ समय बिताना चाहिए। मैं नियमित रूप से उन ब्रेकपॉइंट्स को सेट करता हूं, जिनकी जानकारी में मैं प्रिंट करता हूं और स्वचालित रूप से जारी रहता हूं। हां, यह रनिंग को थोड़ा धीमा कर सकता है, लेकिन ज्यादातर मामलों में यह भारी नहीं है। इसके अलावा, सशर्त टूट जाता है ताकि आप जांच कर सकें कि कुछ अप्रत्याशित कब हुआ।
बिशर्ले

जवाबों:


127

इसे करने का एक तरीका यह है कि अपनी बिल्ड सेटिंग्स में जाएं और डीबग कॉन्फ़िगरेशन के तहत "प्रीप्रोसेसर मैक्रोज़" के लिए एक मान जोड़ें:

DEBUG_MODE=1

सुनिश्चित करें कि आप केवल डिबग कॉन्फ़िगरेशन के लिए ऐसा करते हैं और बीटा या रिलीज़ संस्करणों के लिए नहीं। फिर एक आम हेडर फ़ाइल में आप कुछ ऐसा कर सकते हैं:

#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... ) 
#endif

अब हर जगह NSLog उपयोग के बजाय DLog। परीक्षण और डिबगिंग करते समय, आपको डिबग संदेश मिलेंगे। जब आप बीटा या अंतिम रिलीज़ करने के लिए तैयार होते हैं, तो वे सभी DLogलाइनें स्वचालित रूप से खाली हो जाती हैं और कुछ भी उत्सर्जित नहीं होता है। इस तरह चर की कोई मैन्युअल सेटिंग या NSLogsआवश्यक टिप्पणी नहीं है । अपना बिल्ड टारगेट चुनने पर इसका ध्यान रखा जाता है।


Xcode 4.5 में यह एक चेतावनी देता है जो कहता है: "फ़ंक्शन का दोषपूर्ण घोषणा 'DLog' C99 में अमान्य है" तो यह बात काम नहीं करती है।
सर्गेई ग्रिसकोव

2
@SergiusGee: यदि फ़ंक्शन के लिए घोषणा नहीं मिल रही है, तो आपको लगता है कि आप इसे घोषित करने की कोशिश कर रहे हैं, तो आपको अंतर्निहित घोषणा की चेतावनी मिलती है। सुनिश्चित करें कि आपकी कक्षा के पास हेडर फ़ाइल तक पहुँच है जहाँ यह घोषित किया गया है।
सुडो rm -rf

1
Id लॉग आउट नहीं करता है क्योंकि यह आपको उपयोगकर्ताओं से बेहतर त्रुटि रिपोर्ट प्राप्त करने की क्षमता को लूटता है। Async लॉगिंग और logLevels का उपयोग प्रदर्शन को लगभग शून्य तक सीमित करने के लिए करता है! (देखें कोको
लम्बरजैक

2
मैं #ifdef के बजाय #if के साथ जाऊंगा, क्योंकि DEBUG_MODE 0 अभी भी सही रास्ते से जाएगा
ग्रैडी प्लेयर

1
यह प्रश्न का उत्तर नहीं देता है
मार्टिन मैलोस्टेक

117

Xcode 5 और iOS 7 के लिए अपडेट

नोट: एक्सकोड 7 / स्विफ्ट 2.1 समाधान के लिए एक रिलीज बिल्ड में प्रिंट () स्टेटमेंट निकालने के लिए, यहां मेरा जवाब ढूंढें ।

हां, आपको अपने रिलीज़ कोड में किसी भी NSLog स्टेटमेंट को हटा देना चाहिए, क्योंकि यह आपके कोड को धीमा कर देता है, और रिलीज़ संस्करण में किसी काम का नहीं है। सौभाग्य से, Xcode 5 (iOS 7) में, रिलीज बिल्ड में आपके सभी NSLog स्टेटमेंट 'स्वचालित रूप से' को हटाना आश्चर्यजनक रूप से सरल है। तो क्यों नहीं करते।

पहले 3 कदम उठाने के लिए, फिर कुछ स्पष्टीकरण

1) अपने Xcode प्रोजेक्ट में, 'yourProjectName-prefix.pch' फाइल का पता लगाएं (सामान्य तौर पर आपको यह ग्रुप 'सपोर्टिंग फाइल्स' के तहत मिलेगा, जहां आपकी main.m फाइल स्थित है।

2) '.pch' फ़ाइल के अंत में इन 3 पंक्तियों को जोड़ें:

#ifndef DEBUG
   #define NSLog(...);
#endif

3) अपने 'डीबग' और 'रिलीज़' संस्करण के बीच अंतर का परीक्षण करें। ऐसा करने का एक तरीका 'एडिट स्कीम' -> 'रन ऐप नाम' -> टैब के तहत 'डीबग' के तहत डिबग और रिलीज़ के बीच ड्रॉप-डाउन बॉक्स का उपयोग करना है। रिलीज़ संस्करण में आपको डीबग कंसोल में कोई भी NSLog आउटपुट दिखाई नहीं देगा!

यह सब कैसे काम करता है?

सबसे पहले, किसी को पता होना चाहिए कि एक प्रीप्रोसेसर अपेक्षाकृत 'डंब' है, और कंपाइलर को कॉल करने से पहले सिर्फ 'टेक्स्ट रिप्लेज़र' के रूप में कार्य करता है। यह #defineकथन का अनुसरण करके आपको कुछ भी '#define' बदल देता है ।

#define NSLog(...);

(...)कोष्ठक के बीच 'कुछ भी' () के लिए खड़ा है। ;अंत में भी मन । यह कड़ाई से आवश्यक नहीं है क्योंकि संकलक इसे दूर अनुकूलित करेगा, लेकिन मैं इसे वहां रखना पसंद करता हूं, क्योंकि यह अधिक 'सही' है। हमारे बाद #defineor कुछ नहीं ’है, इसलिए प्रीप्रोसेसर इसे, कुछ नहीं’ के साथ बदल देगा, और इसलिए यह पूरी लाइन को फेंक देगा, NSLog...जब तक और जिसमें से शुरू होता है ;

परिभाषित बयानों का उपयोग कर सशर्त बनाया जा सकता है #ifdef(यदि परिभाषित किया गया है) या #ifndef(यदि परिभाषित नहीं है)

यहाँ हम लिखते हैं #ifndef DEBUG, जिसका अर्थ है 'अगर प्रतीक DEBUG परिभाषित नहीं है'। #ifdefया #ifndefहोने की जरूरत के साथ 'बंद'#endif

डीकोड मोड 'डेबग' होने पर Xcode 5 डिफ़ॉल्ट रूप से हमारे लिए 'DEBUG' प्रतीक को परिभाषित करता है। 'रिलीज़' में यह परिभाषित नहीं है। आप इसे अपनी परियोजना सेटिंग्स के तहत सत्यापित कर सकते हैं, टैब 'सेटिंग बनाएँ' -> नीचे अनुभाग 'Apple LLVM 5.0 - Preprocessing' -> प्रीप्रोसेसर मैक्रोज़ पर स्क्रॉल करें। आप देखेंगे कि रिलीज़ बिल्ड के लिए प्रतीक 'DEBUG' परिभाषित नहीं है!

अंत में, .pch फ़ाइल Xcode द्वारा स्वचालित रूप से बनाई जाती है, और संकलन समय के दौरान स्वचालित रूप से हर स्रोत फ़ाइल में शामिल होती है। तो यह ऐसा है जैसे कि आपने #defineअपनी प्रत्येक स्रोत फ़ाइल में पूरी चीज़ डाल दी होगी ।


1
धन्यवाद @Whasssaaahhh, यह बहुत अच्छा काम करता है। लॉग स्टेटमेंट में कोड डालने से बचें सावधान! प्रीप्रोसेसर पूरे बयानों को हटा देगा NSLogजो कि अंदर है।
एरिक प्लैटन

1
यदि यह एक पुराना प्रोजेक्ट है जिसे प्रीप्रोसेसर मेक्रॉस में डिबग फ्लैग नहीं मिला है, तो यह प्रोजेक्ट के लिए "डिबग = 1" को जोड़ने के लिए आयात किया गया है और टारगेट नहीं
प्रीबे सेप

1
इसके अलावा, कुछ भी न करें NSLogबयान के रूप में उपयोग न करें , उदाहरण के if(AllCool) NSLog(@"Cool!Do Nothing!"); else...लिए NSLogकुछ घुंघराले कोष्ठक में पॉप करेंif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
आर्कडी बॉब

33

ऊपर दिए गए लगभग सभी उत्तर एक समाधान का दावा करते हैं लेकिन समस्या की व्याख्या नहीं करते हैं। मैंने Google में खोज की, और इसका कारण पाया। यहाँ मेरा जवाब है:

हां, यदि आप अपने रिलीज़ संस्करण में NSLog टिप्पणी करते हैं, तो प्रदर्शन बेहतर हो जाएगा। क्योंकि NSLog काफी धीमा है। क्यों? NSLog दो काम करेगा 1) Apple सिस्टम लॉगिंग (ASL), 2) को लॉग संदेश लिखें अगर ऐप xcode में चलता है तो वह stderr को भी लिखता है।

मुख्य समस्या पहले एक में रहती है। थ्रेड को सुरक्षित रखने के लिए, हर बार NSLog को कॉल करने पर, यह ASL सुविधा के लिए एक कनेक्शन खोलता है , संदेश भेजता है, और कनेक्शन को बंद कर देता है। कनेक्शन ऑपरेशन बहुत महंगा है। एक और कारण यह है कि NSLog लॉग इन करने के लिए टाइमस्टैम्प प्राप्त करने के लिए कुछ समय खर्च करता है।

से संदर्भ यहाँ


23

मेरा व्यक्तिगत पसंदीदा एक वैरेडिक मैक्रो का उपयोग करना है।

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif

1
आप इसे कहाँ लगाते हैं?
user6631314

20

उन सभी लोगों के अलावा, जिन्होंने समझदारी से टिप्पणी की कि NSLog()उत्पादन में बिल्कुल भी कॉल नहीं करना थोड़ा तेज है, मैं इसे जोड़ूंगा:

वे सभी NSLog()आउटपुट स्ट्रिंग्स किसी को भी दिखाई देते हैं, जो आपके ऐप को स्टोर से डाउनलोड करता है और इसे डिवाइस के साथ मैक मैक रनिंग एक्सकोड (ऑर्गनाइज़र विंडो के माध्यम से) में चलाता है

आपके द्वारा लॉग की जाने वाली जानकारी (और विशेष रूप से यदि आपका ऐप किसी सर्वर से संपर्क करता है, प्रमाणीकरण करता है, आदि) के आधार पर, यह एक गंभीर सुरक्षा समस्या हो सकती है


जानकारी के लिए धन्यवाद - यह डॉक्टर में कहीं है, या बस खुद को पता चला है? क्या यह स्विफ्ट में प्रिंट के लिए अभी भी सही है?
रॉनी वेब्स

मुझे कोई दस्तावेज पढ़ना याद नहीं है। मैंने अपने डिवाइस पर सिर्फ अपना संग्रहीत निर्माण (उसी बाइनरी जिसे मैंने स्टोर पर सबमिट किया था) स्थापित किया और इसे Xcode में प्लग किया। मुझे कोई पता नहीं है अगर यह स्विफ्ट के लिए समान है print(), लेकिन सबसे अधिक संभावना है।
निकोलस मारी

@ निकोलसमीरी Xcode में खामियों का क्या मतलब है? हम अपने बाइनरी को एक्सकोड में कैसे प्लग कर सकते हैं, वास्तव में मैं वही कोशिश करना चाहता हूं। तो कृपया सुझाव दें। धन्यवाद।
iDevAmit

@iDeveloper मेरा मतलब है कि AppStore से एक डिवाइस (जैसे, एक iPhone) पर अपना ऐप डाउनलोड करें, उस डिवाइस को USB के माध्यम से Xcode में प्लग करें, अपना ऐप लॉन्च करें और Xcode के "डिवाइस" विंडो में लॉग देखें।
निकोलस मियारी

3
@Whasssaaahhh प्रिंट डिवाइस कंसोल में आउटपुट नहीं करता है..मैंने अभी-अभी परीक्षण किया है कि
अनीश पराजुली

13

प्रोजेक्ट डिफ़ॉल्ट सेटिंग

Xcode में प्रोजेक्ट की वर्तमान डिफ़ॉल्ट सेटिंग के अंदर, NS_BLOCK_ASSERTIONSमैक्रो को रिलीज़ संस्करण में 1 और DEBUG=1डेब्यू संस्करण में सेट किया जाएगा ।

तो, मैं निम्नलिखित विधि पसंद करता हूं।

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif

5

हां, आपको इसे निष्क्रिय कर देना चाहिए। खासकर यदि आप अपने कोड की गति को अधिकतम करने की कोशिश कर रहे हैं। NSLogging चीजें बाएं और दाएं प्रदूषित करती हैं सिस्टम लॉग कि अन्य डेवलपर्स के माध्यम से खुदाई करने की कोशिश हो सकती है और यह स्पीड-क्रिटिकल कोड (लूप्स, आदि के अंदर) पर बड़ा प्रभाव डाल सकता है।) मैंने गलती से एक रिकर्सिव फ़ंक्शन में कुछ लॉग संदेश एक बार छोड़ दिए थे "30% की गति वृद्धि के साथ एक अद्यतन जारी करने के लिए मिला है!" कुछ सप्ताह बाद... ;-)


5

सभी अच्छे जवाब, हालांकि यहां एक और छोटी चाल है जिसका उपयोग आप अपने ऐप के मुख्य रूप से विकास / परीक्षण चरणों में कर सकते हैं।

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

चाल:

आप बस .m फ़ाइल के शीर्ष पर अनुवर्ती शामिल करके .m फ़ाइल प्रति NSLog बंद कर सकते हैं :

#define NSLog(...)

( नोट: इस .h फ़ाइल को केवल .m फ़ाइल में मत डालें! )

इसके NSLog()बजाय यह संकलक आपके पूर्वप्रक्रमक मैक्रो का विस्तार करके मूल्यांकन करता है। मैक्रो कुछ नहीं करता है लेकिन तर्कों को छीन लेता है।

यदि आप इसे फिर से चालू करना चाहते हैं तो आप हमेशा उपयोग कर सकते हैं

#undef NSLog

उदाहरण के लिए, आप कुछ खास तरह के तरीकों से किसी विशेष समूह के आसपास NSLog पर कॉल को रोक सकते हैं

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog

3

NSLog धीमा है और इसे रिलीज़ बिल्ड के लिए उपयोग नहीं किया जाना चाहिए। नीचे दिए गए एक साधारण मैक्रो को आप जो भी होना चाहिए उसे अक्षम करने के साथ-साथ अक्षम कर देंगे। कम आम मामले में जहां आप रिलीज़ बिल्ड में NSLog चाहते हैं, बस सीधे कॉल करें। अपने "अन्य c झंडे" बिल्ड सेटिंग्स में "-DNDEBUG" जोड़ने के लिए मत भूलना।

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif


0

इस बारे में क्या?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    

1
यह आउटपुट को निष्क्रिय कर देता है, लेकिन किसी भी प्रसंस्करण समय को नहीं बचाता है, अर्थात NSLog को अभी भी कहा जाता है और इसके तर्क पार्स हुए
dwery

0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

यह अतिरिक्त तर्कों को भी स्वीकार कर लेगा .. बस जरूरत के मुताबिक, सही या गलत के लिए सिर्फ शो-डीबग्लोज़ पैरामीटर मान


यह अच्छा है, लेकिन फिर भी Dlogफ़ंक्शन को पारित किए गए किसी भी तर्क की गणना के सभी ओवरहेड और किसी भी ओवरहेड (और संभावित दुष्प्रभावों) की समस्या है।
टॉड लेहमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.