c अगर मैं आउटपुट को/dev/null में रीडायरेक्ट करता हूं तो क्या प्रिंटफ की लागत अभी भी होगी?




linux performance (4)

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

मेरी टीम के साथी और मेरी असहमति है। वह सोचता है कि हम हर चीज को / dev / null में रीडायरेक्ट कर सकते हैं। यह किसी भी IO का खर्च नहीं उठाएगा ताकि स्नेह कम से कम हो। लेकिन मुझे लगता है कि यह अभी भी सीपीयू खर्च करेगा और हम बेहतर प्रिंट के लिए एक मैक्रो को परिभाषित करते हैं ताकि हम "प्रिंटफ" (शायद सिर्फ वापसी) को फिर से लिख सकें।

इसलिए मुझे इस बारे में कुछ राय चाहिए कि कौन सही है। क्या लिनक्स प्रिंटफ को अनुकूलित करने के लिए पर्याप्त स्मार्ट होगा? मुझे वास्तव में संदेह है।


बहुत ज्यादा।

जब आप प्रोग्राम के स्टैडआउट को /dev/null रीडायरेक्ट करते हैं, तो printf(3) लिए कोई भी कॉल अभी भी सभी तर्कों का मूल्यांकन करेगा, और स्ट्रिंग स्वरूपण प्रक्रिया अभी भी कॉल write(2) से पहले होगी write(2) , जो पूर्ण स्वरूपित स्ट्रिंग लिखती है। प्रक्रिया के मानक उत्पादन के लिए। यह कर्नेल स्तर पर है कि डेटा डिस्क पर नहीं लिखा है, लेकिन विशेष उपकरण /dev/null जुड़े हैंडलर द्वारा त्याग दिया गया है।

तो बहुत अच्छे तरीके से, आप तर्कों का मूल्यांकन करने और उन्हें printf करने के लिए पास करने, printf करने के लिए स्ट्रिंग स्वरूपण कार्य, और कम से कम एक सिस्टम कॉल को वास्तव में डेटा लिखने के लिए, बस उसी आधार पर पुनः निर्देशित करने के लिए बायपास या खाली नहीं करेंगे। /dev/null । ठीक है, यह लिनक्स पर एक वास्तविक अंतर है। कार्यान्वयन केवल उन बाइट्स की संख्या लौटाता है जिन्हें आप लिखना चाहते थे (लिखने के लिए अपने कॉल के 3 तर्क द्वारा निर्दिष्ट write(2) ) और बाकी सब को अनदेखा करें ( यह उत्तर देखें)। आपके द्वारा लिखे जा रहे डेटा की मात्रा और लक्ष्य डिवाइस (डिस्क या टर्मिनल) की गति के आधार पर, प्रदर्शन में अंतर बहुत भिन्न हो सकता है। एम्बेडेड सिस्टम पर, आम तौर पर बोलते हुए, डिस्क को काटकर /dev/null को रीडायरेक्ट करके लिखित डेटा की गैर-तुच्छ राशि के लिए कुछ सिस्टम संसाधनों को बचाया जा सकता है।

हालांकि सिद्धांत रूप में, कार्यक्रम उन मानकों का पता लगा सकता है, जिनके लिए वे (आईएसओ सी और पॉसिक्स) अनुपालन करते हैं, सामान्य कार्यान्वयन की सामान्य समझ के आधार पर कुछ अनुकूलन करते हैं, वे व्यावहारिक रूप से नहीं करते हैं (यानी मैं अनजान हूं) कोई भी यूनिक्स या लिनक्स सिस्टम ऐसा कर रहा है)।

POSIX मानक printf(3) लिए किसी भी कॉल के लिए मानक आउटपुट के लिए लेखन को अनिवार्य करता है, इसलिए संबंधित फाइल डिस्क्रिप्टर के आधार पर कॉल को दबाने write(2) को दबाने के लिए यह मानक-अनुरूप नहीं है। POSIX आवश्यकताओं के बारे में अधिक जानकारी के लिए, आप डेमन का उत्तर पढ़ सकते हैं। ओह, और एक त्वरित नोट: सभी लिनक्स डिस्ट्रोस व्यावहारिक रूप से पोसिक्स-अनुरूप हैं, बावजूद इसके प्रमाणित नहीं होने के बावजूद।

ध्यान रखें कि यदि आप printf पूरी तरह से बदल देते हैं, तो कुछ दुष्प्रभाव गलत हो सकते हैं, उदाहरण के लिए printf("%d%n", a++, &b) । यदि आपको वास्तव में प्रोग्राम निष्पादन पर्यावरण के आधार पर आउटपुट को दबाने की आवश्यकता है, तो एक वैश्विक ध्वज सेट करने पर विचार करें और मुद्रण से पहले ध्वज की जांच करने के लिए प्रिंटफ़ को लपेटें - यह उस कार्यक्रम को धीमा करने के लिए नहीं है जहां प्रदर्शन हानि दिखाई दे रही है के रूप में, एक ही स्थिति की जाँच printf कॉल करने और सभी स्ट्रिंग स्वरूपण की तुलना में बहुत तेज है।


printf फ़ंक्शन stdout को लिखेगा। यह /dev/null लिए अनुकूलित करने के लिए अनुरूप नहीं है। इसलिए, आपके पास प्रारूप स्ट्रिंग को पार्स करने और किसी भी आवश्यक तर्क का मूल्यांकन करने का ओवरहेड होगा, और आपके पास कम से कम एक syscall होगा, साथ ही आप एक बफर को कर्नेल एड्रेस स्पेस में कॉपी करेंगे (जो कि sccall की लागत की तुलना में लापरवाह है) ।

यह उत्तर POSIX के विशिष्ट दस्तावेज पर आधारित है।

सिस्टम इंटरफेस
dprintf, fprintf, printf, snprintf, sprintf - प्रिंट स्वरूपित आउटपुट

Fprintf () फ़ंक्शन आउटपुट को नामित आउटपुट स्ट्रीम पर रखेगा। प्रिंटफ () फ़ंक्शन आउटपुट को मानक आउटपुट स्ट्रीम स्टडआउट पर रखेगा। स्प्रिंटफ () फ़ंक्शन आउटपुट को उसके बाद नल बाइट, '\ 0' के बाद, लगातार बाइट्स में * s पर शुरू करेगा; यह सुनिश्चित करने के लिए उपयोगकर्ता की ज़िम्मेदारी है कि पर्याप्त स्थान उपलब्ध हो।

आधार परिभाषाएँ
करेगा
एक कार्यान्वयन के लिए जो POSIX.1-2017 के अनुरूप है, एक विशेषता या व्यवहार का वर्णन करता है जो अनिवार्य है। एक एप्लिकेशन सुविधा या व्यवहार के अस्तित्व पर भरोसा कर सकता है।


printf फ़ंक्शन stdout को लिखता है। यदि stdout से जुड़ी फ़ाइल डिस्क्रिप्टर को /dev/null पुनर्निर्देशित किया जाता है, तो कोई भी आउटपुट कहीं भी नहीं लिखा जाएगा (लेकिन यह अभी भी लिखा जाएगा), लेकिन printf करने के लिए कॉल और इसे करने वाला स्वरूपण अभी भी होगा।


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

void printf2 (कास्ट चार * फॉर्मस्ट्रिंग, ...);





dev-null