2010-03-17 8 views
5

मैंने अभी सी के साथ शुरुआत की है और malloc() और free() के साथ प्रदर्शन समस्याओं के बारे में बहुत कम ज्ञान है। मेरा सवाल यह है: अगर मुझे malloc() पर पर while लूप के अंदर कॉल करना था, तो 20 पुनरावृत्तियों के लिए लूप, free()को लूप के बाहर कॉल करने की तुलना में धीमी गति से चलेंगे?सी प्रोग्रामिंग: मॉलोक और लूप के भीतर मुफ्त

मैं वास्तव में एक बफर को स्मृति आवंटित करने के लिए पहली विधि का उपयोग कर रहा हूं, फ़ाइल से एक चर-लंबाई स्ट्रिंग पढ़ता हूं, कुछ स्ट्रिंग ऑपरेशन करता हूं, और फिर प्रत्येक पुनरावृत्ति के बाद बफर साफ़ करता हूं। अगर मेरी विधि बहुत अधिक ओवरहेड में परिणाम देती है तो मैं एक ही परिणाम प्राप्त करने के लिए एक बेहतर तरीका पूछना चाहता हूं।

+5

आप पाश बाहर मुक्त फोन नहीं कर सकते हैं इसके अंदर malloc बुला रहे हैं, या आप सभी के लिए स्मृति लेकिन पिछले यात्रा से malloc रिसाव जाएगा। हालांकि, आप malloc के बजाय realloc का उपयोग कर सकते हैं, फिर बाहर मुफ्त। – Cascabel

+0

@ जेफ्रोमी: मुझे लगता है कि आपको उस टिप्पणी को एक उत्तर देना चाहिए। –

+2

आपकी अंग्रेजी ठीक है - यह वास्तव में एसओ पर अधिकांश नौसिखियों की अंग्रेजी की तुलना में बेहतर है। –

उत्तर

13

निश्चित रूप से धीमी एक बेंचमार्क के निर्माण के लिए है ...। (लेकिन तुम malloc और free की संख्या को संतुलित करने अन्यथा आप एक स्मृति रिसाव पाने की जरूरत है याद है।)

भिन्न-भिन्न होती हैं, तो आप realloc का उपयोग बफर आकार का विस्तार कर सकते हैं।

void* v = malloc(1024); 
size_t bufsize = 1024; 

while(cond) { 
    size_t reqbufsize = get_length(); 
    if (reqbufsize > bufsize) { 
     bufsize = reqbufsize * 2; 
     v = realloc(v, bufsize); 
    } 
    // you may shrink it also. 

    do_something_with_buffer(v); 
} 

free(v); 
+2

+1 - लेकिन आपको नहीं लगता कि 'bufsize = reqbufsize * 2;' थोड़ा कठोर है? : पी –

+0

शायद। 'Std :: vector' के MSVC2k8 कार्यान्वयन को फिर से आवंटित करते समय अपने बफर को 150% तक बढ़ा देता है। –

+4

@ बिलीओनेल: यह वास्तव में चीजों को करने का एक बहुत ही आम तरीका है। – Dinah

3

यदि आप बफर की अधिकतम लंबाई जानते हैं - या उचित अधिकतम सेट कर सकते हैं - तो आप प्रत्येक पुनरावृत्ति के लिए एक ही बफर का उपयोग कर सकते हैं। अन्यथा आप जो कर रहे हैं वह ठीक होना चाहिए।

0

यह मॉलोक और मुफ्त के कार्यान्वयन पर निर्भर करता है।

अपने प्रश्न का उत्तर देने के लिए सबसे अच्छा तरीका है

1

यह इस बात पर निर्भर करता है कि आपको बफर की आवश्यकता है।

क्या आपको वास्तव में प्रत्येक पुनरावृत्ति के बाद इसे साफ़ करने की आवश्यकता है या अंत में \0 char स्ट्रिंग के अंत को चिह्नित करने के लिए पर्याप्त होगा? इसके बाद विभिन्न str लाइब्रेरी कॉल का उपयोग किया जाता है।

यदि आपको वास्तव में इसे साफ़ करने की आवश्यकता है तो आप bzero() का उपयोग कर सकते हैं। निश्चित रूप से हर पुनरावृत्ति पर मॉलोकिंग और फ्रीिंग संसाधनों का अपशिष्ट है, क्योंकि आप खुशी से बफर का पुनः उपयोग कर सकते हैं।

यदि आप लूप के समानांतर करना चाहते हैं तो एक अलग समस्या उत्पन्न होगी, यानी इसका उपयोग करके कई समवर्ती धागे हैं।

सरल, वास्तविक जीवन उदाहरण: पानी ले जाने के लिए एक बाल्टी का उपयोग करना। मान लीजिए कि आपको उस बाल्टी के साथ कई यात्रा करने की ज़रूरत है: क्या इसे समझने, इसे इस्तेमाल करने, इसे नीचे रखने, इसे फिर से लेने, इसका उपयोग करने, आदि का अर्थ समझ जाएगा ...? आप बाल्टी को यथासंभव बार-बार उपयोग कर सकते हैं। दूसरी तरफ, बाल्टी को आपके और अधिक लोगों द्वारा उपयोग करने की आवश्यकता है, या तो आप बाल्टी तक पहुंच व्यवस्थित करते हैं या अधिक बाल्टी की आवश्यकता होती है।

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

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

कुल्ला, दोहराना।

ps: औसत समय में मजा लें। यह दिलचस्प होना चाहिए, निराशाजनक नहीं है।

1

आम तौर पर एक लूप के बाहर स्थानांतरित किया जा सकता है जो कुछ भी होना चाहिए। एक ही कार्रवाई दोहराएं जब आप इसे एक बार कर सकते हैं?

जस्टिन एथियर सही है, एक बफर आवंटित करें जो सबसे बड़ी स्ट्रिंग को आराम से फिट करेगा और इसका पुन: उपयोग करेगा।

6

20 पुनरावृत्तियों के लिए, आपको malloc/free के प्रदर्शन के बारे में चिंता नहीं करना चाहिए।

यहां तक ​​कि बहुत अधिक (परिमाण के कुछ आदेश) के लिए, आपको अनुकूलन के बारे में सोचना शुरू नहीं करना चाहिए जब तक कि आप कोड को प्रोफ़ाइल न करें और समझें कि धीमा क्या है।

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

6

आप पाश बाहर मुक्त कॉल नहीं कर सकते अगर आप अंदर malloc बुला रहे हैं:

char * buffer; 
for (int i = 0; i < num_files; i++) { 
    buffer = malloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 

आप num_files बार malloc'ed गया होगा, लेकिन केवल एक बार मुक्त कर दिया - आप, लेकिन पिछले सभी से स्मृति लीक !

दो मुख्य विकल्प हैं - पाश से पहले malloc (या सिर्फ एक सरणी का उपयोग करें) यदि आप एक आकार है कि सब कुछ के लिए काम करेंगे, या realloc का उपयोग पता है:

char * buffer = NULL; 
for (int i = 0; i < num_files; i++) { 
    buffer = realloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 
0

प्रक्रिया बेहतर। कुछ छद्म कोड है:

#define BLOCK_SIZE 1024 // or about the bigger size of your strings. 

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++) 
{ 
    while (more bytes left to read) 
    { 
    read full string or BLOCK_SIZE bytes at max // most calls work this way 
    proces bytes in buffer 
    } 
} 

free(buffer); 
संबंधित मुद्दे