2012-07-19 17 views
9

मैं अभी भी अपने कोड में क्या हो रहा है, यह जानने के लिए कंसोल आउटपुट का उपयोग करता हूं। मैं इस एक सा पुराना फैशन हो सकता है, लेकिन मैं यह भी लॉग फाइल आदि में करने के लिए "पाइप" stdout इस का उपयोगसी: एक fprintf (stdout, ....) इतनी धीमी क्यों है?

हालांकि, यह पता चला है कि कंसोल के लिए उत्पादन कुछ कारण के लिए धीमा है। मैं सोच रहा था कि कोई व्यक्ति समझा सकता है कि क्यों एक fprintf() को एक कंसोल विंडो में अवरुद्ध करना प्रतीत होता है।

मैंने क्या किया गया है/अब तक का निदान: 0.82ms (औसत में):

  1. मैं समय एक सरल fprintf(stdout,"quick fprintf\n"); यह जरूरत मापा जाता। यह बहुत लंबे समय तक माना जाता है क्योंकि vsprintf_s(...) एक ही आउटपुट को केवल कुछ माइक्रोसेकंड में एक स्ट्रिंग में लिखता है। इसलिए कुछ विशेष रूप से कंसोल के लिए अवरुद्ध होना चाहिए।

  2. अवरोध से बचने के लिए मैंने vsprintf_s(...) का उपयोग अपने आउटपुट को एक फीफो समान डेटा संरचना में कॉपी करने के लिए किया है। डेटा संरचना एक महत्वपूर्ण खंड वस्तु द्वारा संरक्षित है। कतारबद्ध आउटपुट को कंसोल पर डालकर एक अलग धागा डेटा संरचना को अनदेखा कर रहा है।

  3. एक और सुधार मैं पाइप सेवाओं के परिचय से प्राप्त कर सकता हूं।

    • एक vsprintf_s(...) सरल तार करने के लिए उत्पादन प्रारूप: मेरा कार्यक्रम (एक कंसोल विंडो में समाप्त करने की अपेक्षा की) के उत्पादन में निम्नलिखित रास्ता चला जाता है।
    • तारों को उदाहरण के लिए एक लिंक्ड सूची संरचना, एक फीफो समान डेटा संरचना में कतारबद्ध किया गया है। यह डेटा संरचना एक महत्वपूर्ण खंड ऑब्जेक्ट द्वारा संरक्षित है।
    • एक दूसरा थ्रेड आउटपुट स्ट्रिंग को नामित पाइप पर भेजकर डेटा संरचना को हटा देता है।
    • एक दूसरी प्रक्रिया नामित पाइप को पढ़ती है और स्ट्रिंग को फिर से एक फीफो को डेटा संरचना में डाल देती है। ब्लॉकिंग आउटपुट से कंसोल तक पढ़ने को दूर रखने के लिए इसकी आवश्यकता है। रीडिंग प्रक्रिया नामित पाइप पढ़ने में तेजी से है और पाइप बफर के भरने के स्तर पर लगातार निगरानी रखती है।
    • उस दूसरी प्रक्रिया में एक दूसरा धागा अंततः डेटा संरचना को fprintf(stdout,...) कंसोल पर हटा देता है।

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

यह सुनिश्चित करने के लिए बहुत सी चीजें हैं कि कंसोल आउटपुट "गैर-अवरुद्ध" है। लेकिन परिणाम बहुत बुरा नहीं है। मेरा मुख्य कार्यक्रम केवल कुछ microseconds के भीतर जटिल fprintf (stdout, ...) लिख सकता है।

शायद मुझे पहले पूछा जाना चाहिए था: क्या कोई अन्य (आसान!) तरीका कंसोल आउटपुट को अनब्लॉक करने का तरीका है?

+6

मुझे संदेह है कि यह कंसोल है जो धीमा है। टर्मिनल अनुकरणकर्ता धीमे होते हैं (क्योंकि उनकी बॉड दर उनके विनिर्देशों का हिस्सा है)। क्या आपने बस कुछ समय में * stdout * को पुनर्निर्देशित करते समय उस समय को माप लिया था? और आप डीबगिंग जानकारी को किसी अन्य 'फ़ाइल' पर आउटपुट कर सकते हैं (और एक बड़े बफर के साथ 'setvbuf' का उपयोग करें)। –

+0

आप किस ऑपरेटिंग सिस्टम, पुस्तकालय, कंपाइलर के साथ काम कर रहे हैं? –

+0

'fprintf' द्वारा लिया गया समय बहुत दिलचस्प नहीं है यदि आप यह भी नहीं जानते कि आउटपुट चैनल के लिए कितना समय व्यतीत किया जाता है। –

उत्तर

12

मुझे लगता है कि समय की समस्या को इस तथ्य के साथ करना है कि कंसोल लाइन डिफ़ॉल्ट रूप से buffered है।इसका मतलब यह है कि हर बार जब आप '\n' चरित्र लिखते हैं, तो आपका संपूर्ण आउटपुट बफर कंसोल पर भेजा जाता है, जो कि एक महंगा ऑपरेशन है। यह वह कीमत है जिसे आप आउटपुट में तुरंत दिखाई देने के लिए लाइन के लिए भुगतान करते हैं।

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

इससे पहले कि आप पहले कंसोल के लिए लिखना इस कॉल करें:

char buf[10000]; 
setvbuf(stdout, buf, _IOFBF, sizeof(buf)); 

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

+0

परीक्षण, पुष्टि, महान जवाब। मुझे आशा थी कि – Arno

+0

को गति देने के लिए कुछ चाल थी, निश्चित रूप से जादू निरंतर दोहराने के बजाय इसे 'sizeof buf' का उपयोग करना चाहिए। :) – unwind

+0

@unwind बेशक, आप सही हैं! यह मेरे हिस्से पर एक स्पष्ट चूक था, आप मेरे जवाबों को संपादित करने के लिए आपका स्वागत करते हैं जब आप मुझे इस तरह मूर्खतापूर्ण कुछ देखते हैं :) बहुत बहुत धन्यवाद! – dasblinkenlight

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