2010-11-16 15 views
12

हमारे पास एक पायथन आधारित वेब सर्वर है जो cPickle का उपयोग करके स्टार्टअप पर कई बड़ी डेटा फ़ाइलों को अनपिक करता है। डेटा फाइलें (HIGHEST_PROTOCOL का उपयोग करके मसालेदार) डिस्क पर लगभग 0.4 जीबी हैं और 1.2 जीबी पायथन ऑब्जेक्ट्स के रूप में मेमोरी में लोड होती हैं - इसमें 20 सेकंड लगता है। हम 64-बिट विंडोज मशीनों पर पायथन 2.6 का उपयोग कर रहे हैं।सीजीकल की तुलना में पाइथन में 1 जीबी ऑब्जेक्ट्स को deserialize कैसे करें?

टोंटी निश्चित रूप से डिस्क नहीं है (यह कम से कम 0.5s लेता है वास्तव में इतना डेटा पढ़ने के लिए), लेकिन स्मृति आवंटन और ऑब्जेक्ट निर्माण (वहाँ बनाया जा रहा वस्तुओं के लाखों रहे हैं)। हम स्टार्टअप समय को कम करने के लिए 20s को कम करना चाहते हैं।

क्या cPickle (5-10x की तरह) से अधिक तेज़ पाइथन में 1 जीबी से अधिक वस्तुओं को deserialize करने का कोई तरीका है? चूंकि निष्पादन समय स्मृति आवंटन और ऑब्जेक्ट सृजन से बंधे हैं, इसलिए मुझे लगता है कि जेएसओएन जैसी कोई और अनपिक्लिंग तकनीक का उपयोग नहीं करेगा।

मैं कुछ व्याख्या भाषाओं एक डिस्क फ़ाइल के रूप में अपनी पूरी स्मृति छवि बचाने के लिए एक रास्ता है पता है, ताकि वे इसे स्मृति में वापस एक ही बार में सभी लोड कर सकते हैं, बिना प्रत्येक वस्तु के लिए आवंटन/निर्माण। क्या ऐसा करने का कोई तरीका है, या पाइथन में ऐसा कुछ हासिल करना है?

+1

यह एक सॉलिड स्टेट ड्राइव पाने के लिए अपने मौका हो सकता है। क्या यह देव को तेज करने के लिए है? आपको त्वरित तैनाती करने की अनुमति देने के लिए? क्या डेटा पढ़ने या इसे अनपिक करने में अंतराल है? यदि आप एक खाली उदाहरण के साथ शुरू करते हैं, तो स्टार्ट अप टाइम क्या है? – Scott

+0

ध्यान दें कि मैंने अपने प्रश्न में उल्लेख किया है कि बाधा ड्राइव/पढ़ने की गति नहीं है, लेकिन अनपिकलिंग और ऑब्जेक्ट सृजन की गति है। यह त्वरित तैनाती के लिए अधिक है - हमारे सर्वर को जल्दी से पुनरारंभ करने की अनुमति देने के लिए। मुझे पूरा यकीन नहीं है कि आपका मतलब "खाली उदाहरण" से क्या है। –

+0

एक 750MB अचार बाइनरी फ़ाइल के लिए, gc.disable साथ cPickle लोड कॉल()/gc.enable (लपेटकर) काफी कुल समय के आसपास 20x के लिए आवश्यक कम कर दिया। देखें [यहां] (http://stackoverflow.com/a/36699998/2385420) –

उत्तर

16
  1. मार्शल मॉड्यूल का प्रयास करें - यह आंतरिक (बाइट-संकलक द्वारा प्रयुक्त) और जानबूझकर ज्यादा विज्ञापित नहीं है, लेकिन यह बहुत तेजी से है। ध्यान दें कि यह अचार जैसे उदाहरणों को क्रमबद्ध नहीं करता है, केवल बिल्टिन प्रकार (सटीक बाधाओं को याद न करें, दस्तावेज़ देखें)। यह भी ध्यान रखें कि प्रारूप स्थिर नहीं है।

  2. यदि आपको कई प्रक्रियाओं को प्रारंभ करने की आवश्यकता है और एक प्रक्रिया को हमेशा लोड किया जा सकता है, तो एक सुरुचिपूर्ण समाधान है: वस्तुओं को एक प्रक्रिया में लोड करें, और फिर मांग पर प्रक्रियाओं को छोड़कर इसमें कुछ भी नहीं करें। फोर्किंग तेज है (लिखने पर प्रतिलिपि) और सभी प्रक्रियाओं के बीच स्मृति साझा करता है। [अस्वीकरण: अनचाहे; unlike Ruby, अजगर रेफरी गिनती पेज प्रतियां ट्रिगर किया जाएगा अगर आप विशाल वस्तुओं है और/या उनमें से एक छोटा सा अंश का उपयोग तो यह शायद बेकार है।]

  3. यदि आपका वस्तुओं NumPy सरणी की तरह कच्चे डेटा के बहुत सारे होते हैं, आप उन्हें बहुत तेजी से स्टार्टअप के लिए स्मृति-मानचित्र कर सकते हैं। इन परिदृश्यों के लिए pytables भी अच्छा है।

  4. आप केवल वस्तुओं के एक छोटे से हिस्से का उपयोग करेंगे, तो एक OO डेटाबेस (Zope की तरह) शायद आप कर सकते हैं। यद्यपि यदि आपको स्मृति में सभी की आवश्यकता है, तो आप थोड़ा लाभ के लिए बहुत सारे ओवरहेड बर्बाद कर देंगे। (कभी भी इस्तेमाल नहीं किया जाता है, इसलिए यह बकवास हो सकता है)।

  5. हो सकता है कि अन्य अजगर कार्यान्वयन यह कर सकते हैं? पता नहीं है, सिर्फ एक विचार ...

+0

धन्यवाद, सहायक सामान। एफवाईआई, बहुत सारी वस्तुओं के साथ एक बड़ी फाइल पर मेरे त्वरित परीक्षण में, marshal.loads() pickle.loads() के रूप में लगभग दोगुना था। –

+0

यहां एक विशाल शब्दकोश पर समान अनुभव; marshal.load केवल 0.78s लेता है, जहां cPickle.load 1.2s लेता है। – unhammer

+0

विकल्प संख्या दो समस्याग्रस्त हो जाएगा, क्योंकि प्रत्येक ऑब्जेक्ट को संदर्भित करने के पल में प्रत्येक फोर्कड उप-प्रक्रिया के लिए वस्तुओं की प्रतिलिपि बनाई जाएगी। ऐसा इसलिए है क्योंकि प्रत्येक ऑब्जेक्ट में एक रेफरी गिनती होती है जो हर बार ऑब्जेक्ट तक पहुंचने पर बदलती है। यह बदले में वस्तु को बदलने जैसा है और इस प्रकार स्मृति को कॉपी करने का कारण बनता है। अनिवार्य रूप से लिखने पर प्रतिलिपि प्राप्त होने पर प्रतिलिपि बन जाती है जब पाइथन का संबंध है ... – FableBlaze

3

मैंने सीपीकल (या पायथन) का उपयोग नहीं किया है, लेकिन इस तरह के मामलों में मुझे लगता है कि सबसे अच्छी रणनीति वस्तुओं की अनावश्यक लोडिंग से बचने के लिए वास्तव में आवश्यक है - एक अलग थ्रेड पर शुरू होने के बाद लोड कहें, वास्तव में स्पष्ट कारणों से किसी भी समय अनावश्यक लोडिंग/प्रारंभिकरण से बचने के लिए यह आमतौर पर बेहतर होता है। Google 'आलसी लोडिंग' या 'आलसी प्रारंभिक'। यदि आपको सर्वर शुरू होने से पहले कुछ कार्य करने के लिए वास्तव में सभी ऑब्जेक्ट्स की आवश्यकता होती है तो हो सकता है कि आप मैन्युअल कस्टम deserialization विधि को लागू करने का प्रयास कर सकते हैं, दूसरे शब्दों में कुछ खुद को लागू करें यदि आपके पास उस डेटा का अंतरंग ज्ञान है जिसके साथ आप निपटेंगे 'निचोड़' बेहतर प्रदर्शन तो इसके साथ निपटने के लिए सामान्य उपकरण।

3

आप HIGHEST_PROTOCOL का उपयोग नहीं कर से अचार बनाने की दक्षता त्याग की कोशिश की? यह स्पष्ट नहीं है कि इस प्रोटोकॉल का उपयोग करने के साथ प्रदर्शन लागत क्या है, लेकिन यह एक कोशिश के लायक हो सकता है।

+0

अच्छा विचार। हालांकि, हम पहले डिफ़ॉल्ट (निम्नतम) प्रोटोकॉल का उपयोग कर रहे थे, लेकिन HIGHEST_PROTOCOL (एक बाइनरी-आधारित प्रोटोकॉल) पर स्विच करने से इसे दो के कारक से बढ़ा दिया गया। तो HIGHEST_PROTOCOL निश्चित रूप से तेज़ है। –

2

असंभव के बारे में डेटा किस तरह आप लोड हो रहा है और आप इसे कैसे उपयोग कर रहे हैं और अधिक जानने के बिना इस जवाब देने के लिए।

यदि यह व्यापार तर्क किसी प्रकार का है, हो सकता है आप इसे एक पूर्व संकलित मॉड्यूल में बदल की कोशिश करनी चाहिए;

यह डेटा संरचित है, तो आप इसे एक डेटाबेस को सौंप सकते हैं और केवल खींच क्या आवश्यकता है?

क्या डेटा में नियमित संरचना है? क्या इसे विभाजित करने और क्या आवश्यक है तय करने का कोई तरीका है और केवल तभी लोड करें?

7

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

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

+1

जिस व्यक्ति ने मुझे दिया है -1: जीत पर पढ़ने (1) को कॉल करके फ़ाइल लोड करने का प्रयास करें; फिर यूनिक्स पर ऐसा करने का प्रयास करें। विंडोज़ पर कुछ मेगाबाइट पढ़ने में कई सेकंड लगते हैं; यह अभी भी यूनिक्स पर तत्काल है। यदि बेनहॉइट फाइल से कई लाखों pickle.load() कॉल को कॉल करके कई ऑब्जेक्ट्स लोड कर रहा है, तो यह एक कारक हो सकता है। – ondra

+0

अच्छी कॉल। हमारे डेटा पर, "obj = pickle.load (f)" को "s = f.read() में बदलना; obj = pickle.loads (ओं)" 30% की गति वृद्धि देता है। परिमाण के आदेश नहीं, लेकिन इसके बारे में जानने लायक है। (Btw, मैं गलती से ऊपर के बजाय नीचे दबाया, अपने जवाब देने के लिए एक छोटी सी संपादन कर लेने के लिए स्वतंत्र महसूस इसलिए मैंने इसे वोट दें सकते हैं।) –

+0

मैं वहाँ पाया मार्शल मॉड्यूल के साथ एक ही प्रक्रिया करने के लिए एक सुंदर पर्याप्त सुधार होने के लिए (बनाता है क्योंकि यह एक विंडोज़ समस्या है)। –

2

मैं एक जवाब है कि उपयोगी हो सकता है जोड़ देंगे - अगर आप कर सकते हैं, तो आप _ परिभाषित करने की कोशिश कर सकते हैं स्लॉट्स _ वर्ग है कि सबसे अधिक पर बनाया था? यह थोड़ा सीमित और असंभव हो सकता है, हालांकि ऐसा लगता है कि मेरे परीक्षण पर शुरुआत के लिए आवश्यक समय में कटौती की गई है।

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

  • कोई संबंधित समस्या नहीं^_^