2012-01-17 20 views
13

मैं टेक्स्ट डेटा की स्ट्रीम को संपीड़ित करने के लिए zlib का उपयोग कर रहा हूं। पाठ डेटा भाग में आता है, और प्रत्येक खंड के लिए, deflate() कहा जाता है, फ्लश सेट Z_NO_FLUSH पर सेट किया जाता है। एक बार सभी हिस्सों को पुनर्प्राप्त कर लिया गया है, deflate() को Z_FINISH पर फ्लश सेट के साथ बुलाया जाता है।zlib, डिफ्लेट: आवंटित करने के लिए कितनी मेमोरी है?

स्वाभाविक रूप से, deflate() प्रत्येक कॉल पर संकुचित आउटपुट का उत्पादन नहीं करता है। यह उच्च संपीड़न दर प्राप्त करने के लिए आंतरिक रूप से डेटा जमा करता है। और यह ठीक है! प्रत्येक बार deflate() संपीड़ित आउटपुट उत्पन्न करता है, यह आउटपुट डेटाबेस फ़ील्ड में जोड़ा जाता है - एक धीमी प्रक्रिया।

हालांकि, deflate() संपीड़ित डेटा उत्पन्न करता है, तो वह डेटा प्रदत्त आउटपुट बफर, deflate_out में फिट नहीं हो सकता है। इसलिए deflate() पर कई कॉल की आवश्यकता है।

वहाँ deflate_out हमेशा इतना बड़ा बनाने के लिए इतना है कि deflate() यह सभी संकुचित डेटा स्टोर कर सकते हैं एक रास्ता है, हर बार यह उत्पादन का उत्पादन करने का फैसला करता: और है कि मैं क्या करने से बचना चाहते है?

नोट्स:

  • असंपीड़ित डेटा का कुल आकार नहीं पहले से जाना जाता है। जैसा ऊपर बताया गया है, असम्पीडित डेटा भाग में आता है, और संपीड़ित डेटा को डेटाबेस फ़ील्ड में भी जोड़ दिया जाता है।

  • फ़ाइल में शामिल हैं zconf.h मुझे निम्नलिखित टिप्पणी मिली है। क्या वह शायद मैं क्या देख रहा हूं? अर्थात। (1 << (windowBits+2)) + (1 << (memLevel+9)) संकुचित डेटा के बाइट्स में अधिकतम आकार deflate() उत्पन्न कर सकता है?

    /* The memory requirements for deflate are (in bytes): 
          (1 << (windowBits+2)) + (1 << (memLevel+9)) 
    that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) 
    plus a few kilobytes for small objects. For example, if you want to reduce 
    the default memory requirements from 256K to 128K, compile with 
        make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" 
    Of course this will generally degrade compression (there's no free lunch). 
    
        The memory requirements for inflate are (in bytes) 1 << windowBits 
    that is, 32K for windowBits=15 (default value) plus a few kilobytes 
    for small objects. 
    */ 
    
+0

देखें http://stackoverflow.com/questions/4936255/zlib-how-to-dimension-avail-out – nos

+2

@nos: इनपुट का आकार ज्ञात होने पर यह केवल सहायक है। –

+0

मैंने संपीड़न के लिए स्मृति आवश्यकता होने के लिए 'zconf.h' में टिप्पणी पढ़ी, आउटपुट बफर का आकार नहीं। उसने कहा, यह तार्किक लगता है कि आउटपुट बफर के लिए ऊपरी बाउंड कुल स्मृति आवश्यकताओं (128K + 128K + "कुछ किलोबाइट्स" उपर्युक्त उदाहरण में है) + हेडर लम्बाई (40 बाइट)। –

उत्तर

5

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

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

अधिक आउटपुट के लिए डिफ्लेट() को कॉल करने से बचने के लिए कोई बात नहीं है।यदि आप डिफ्लेट() पर बस लूप करते हैं, तब तक जब तक आपके पास कोई आउटपुट नहीं होता है, तो आप एक बार एक निश्चित आउटपुट बफर का उपयोग कर सकते हैं। इस प्रकार डिफ्लेट() और फुलाए() इंटरफ़ेस का उपयोग करने के लिए डिज़ाइन किया गया था। आप इंटरफेस का उपयोग करने के तरीके के एक अच्छी तरह से प्रलेखित उदाहरण के लिए http://zlib.net/zlib_how.html देख सकते हैं।

वैसे, zlib (1.2.6) के नवीनतम संस्करण में एक deflatePending() फ़ंक्शन है जो आपको यह बताता है कि आउटपुट डिफ्लेट() कितना वितरण करने का इंतजार कर रहा है।

+0

इस विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद! अगले कॉल के लिए आवश्यक डिफ्लेट() 'के लिए आवश्यक आउटपुट बफर की भविष्यवाणी करने के लिए, मैंने' deflatePending() 'और' deflateBound() 'द्वारा लौटाए गए मान को जोड़कर आकार जोड़ा। यह @EugenRieck द्वारा सुझाव के समान है। हालांकि, जैसा कि मैं इसे समझता हूं, यह एक अच्छा विचार नहीं है क्योंकि 'deflateBound()' को केवल तभी काम करने के लिए दस्तावेज किया जाता है जब पूरे इनपुट के आकार को संपीड़ित किया जाता है। अर्थात। 'deflateBound()' इनपुट के हिस्सों के लिए काम करने के लिए दस्तावेज नहीं है। – feklee

+1

डिफ्लेट बाउंड() इनपुट के हिस्सों के लिए काम कर सकता है, लेकिन केवल अगर पिछले सभी इनपुट को संपीड़ित और उत्सर्जित किया गया था। यह केवल Z_NO_FLUSH के अलावा फ्लश विकल्प का उपयोग करके और पिछले कॉल पर सभी आउटपुट का उपभोग करके आश्वासन दिया जा सकता है। इस मामले में, deflatePending() Z_BLOCK या Z_PARTIAL_FLUSH का उपयोग करने के लिए उपयोगी होगा, क्योंकि वे पीछे कुछ बिट छोड़ सकते हैं। Z_NO_FLUSH का उपयोग करते समय, deflateBound() + deflatePending() में तीसरा टुकड़ा गुम हो जाएगा, जो पिछले डिफ्लेट() कॉल पर खपत इनपुट का आकार है, लेकिन अभी तक संपीड़ित और उत्सर्जित नहीं है। –

2

जबकि एक संकेत के लिए स्रोतों को देखते हुए, मैं

/* ========================================================================= 
* Flush as much pending output as possible. All deflate() output goes 
* through this function so some applications may wish to modify it 
* to avoid allocating a large strm->next_out buffer and copying into it. 
* (See also read_buf()). 
*/ 
local void flush_pending(strm) 
    z_streamp strm; 
{ 
    unsigned len = strm->state->pending; 
... 

से अधिक गिर गया() Deflate भर शून्य flush_pending() के उपयोग का पता लगाने से पता चलता है, कि जरूरत पर एक ऊपरी बाध्य स्ट्रीम के बीच में आउटपुट बफर

strm->state->pending + deflateBound(strm, strm->avail_in) 

पहला भाग पिछली कॉल से पाइप में अभी भी डेटा के लिए खाता है deflate(), दूसरे भाग लंबाई avail_in के अभी तक संसाधित डेटा के लिए खाते हैं।

+0

आप मेरे अभी हटाए गए उत्तर पर टिप्पणी में सही थे। मैं आंतरिक राज्य के बारे में भूल रहा था। जिज्ञासा से, मैंने एक त्वरित परीक्षण में डिफ्लेट करने के लिए पहली कॉल के बाद उस लंबित मूल्य को देखा। Avail_in शून्य था, avail_out 2 था, और लंबित शून्य (0) था। यह लंबित डेटा की वास्तविक राशि को प्रतिबिंबित नहीं करता था। फ्लैश करने के लिए डिफ्लेट करने के लिए अगली कॉल आउटपुट में ~ 8K डंप हो गई। तो यह कम से कम एक स्थिति में एक सटीक माप नहीं हो सकता है। –

+0

आप कहते हैं कि 'strm-> state-> लंबित' पाइप * में अभी भी डेटा का आकार है। अगर मैं इसे सही ढंग से समझता हूं, तो यह आकार प्रत्येक कॉल के साथ 'deflate()' तक बढ़ जाता है, जब तक कि अज्ञात ऊपरी सीमा तक नहीं पहुंच जाती। और यह ऊपरी बाउंड ठीक वही है जो मैं ढूंढ रहा हूं। तो यह कैसे सहायक है? क्या मैं कुछ भूल रहा हूँ? – feklee

+0

मेरा मतलब था, कि अगर आप डिफ्लेट() को आकार के एक बफर-> राज्य-> लंबित + डिफ्लेट बाउंड (strm, strm-> avail_in) देते हैं तो यह कभी भी बफर स्पेस से बाहर नहीं होगा। –

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