2009-10-19 8 views
5

हमारे पास कोड का एक परिपक्व निकाय है जो फ़ाइलों से डेटा को डेटाबेस में लोड करता है। कई फ़ाइल प्रारूप हैं; वे सभी निश्चित चौड़ाई वाले क्षेत्र हैं।मैं पर्ल की निश्चित चौड़ाई डेटा की प्रसंस्करण को कैसे बढ़ा सकता हूं?

कोड का हिस्सा पैकेज चर में इनपुट डेटा से फ़ील्ड पढ़ने के लिए पर्ल unpack() फ़ंक्शन का उपयोग करता है। व्यापार तर्क तब इन क्षेत्रों को 'मानव-पठनीय' तरीके से संदर्भित करने में सक्षम है।

फ़ाइल पढ़ने से पहले फ़ाइल पढ़ने कोड एक प्रारूप विवरण से उत्पन्न होता है।

स्केच रूप में, उत्पन्न कोड इस तरह दिखता है:

while (<>) { 

    # Start of generated code. 

    # Here we unpack 2 fields, real code does around 200. 
    ($FIELDS::transaction_date, $FIELDS::customer_id) = unpack q{A8 A20}; 

    # Some fields have leading space removed 
    # Generated code has one line like this per affected field. 
    $FIELDS::customer_id =~ s/^\s+//; 

    # End of generated code. 

    # Then we apply business logic to the data ... 
    if ($FIELDS::transaction_date eq $today) { 
     push @fields, q{something or other}; 
    } 

    # Write to standard format for bulk load to the database. 
    print $fh join('|', @fields) . q{\n} or die; 
} 

कोड रूपरेखा का पता चलता है कि समय की लगभग 35% खोल में बिताया है और अग्रणी अंतरिक्ष पट्टी है। शेष समय डेटा को सत्यापित करने और बदलने और आउटपुट फ़ाइल में लिखने में व्यतीत होता है।

ऐसा प्रतीत होता है कि व्यापार तर्क का कोई भी हिस्सा नहीं है जो रन टाइम के 1-2% से अधिक लेता है।

सवाल यह है कि - क्या हम किसी भी तरह से अनपॅकिंग और स्पेस स्ट्रिपिंग से थोड़ी अधिक गति प्राप्त कर सकते हैं? अधिमानतः FIELDS पैकेज चर को संदर्भित करने वाले सभी कोड को दोबारा प्रतिक्रिया देने के बिना।

संपादित करें:

मामले में यह एक फर्क नहीं पड़ता

$ perl -v 
This is perl, v5.8.0 built for PA-RISC1.1 
+0

यह जानने में रुचि होगी कि अनपैक के बाईं ओर पैकेज चर की सूची का उपयोग इष्टतम होने की संभावना है। –

उत्तर

1

हां। substr का उपयोग करके निकालने का यह करने का सबसे तेज़ तरीका होने की संभावना है। वह है:

$FIELDS::transaction_date = substr $_, 0, 8; 
$FIELDS::customer_id  = substr $_, 8, 20; 

तेजी से होने की संभावना है। अब, अगर मैं इस कोड को हस्तलेखित कर रहा था, तो मैं unpack नहीं छोड़ूंगा, लेकिन यदि आप कोड उत्पन्न कर रहे हैं, तो आप इसे एक शॉट और माप भी दे सकते हैं।

भी देखें Is Perl’s unpack() ever faster than substr()?

प्रमुख रिक्त स्थान अलग करना के लिए के रूप में के लिए जवाब, s/^\s+// सबसे तेजी से विधि होने की संभावना है।

अद्यतन: बेंचमार्क चलाने में सक्षम होने के बिना कुछ भी निश्चित कहना मुश्किल है। हालांकि, कैसे के बारे में:

my $x = substr $_, 0, 8; 

क्षेत्रों है कि किसी भी trimming और

my ($y) = substr($_, 8, 20) =~ /\A\s+(.+?)\s+\z/; 

कि ट्रिमिंग की क्या ज़रूरत है की जरूरत नहीं है के लिए?

+0

मैं प्रयोग और रिपोर्ट करूँगा। –

+3

ध्यान देने योग्य एक बात यह है कि 'ए' स्ट्रिप्स को मुक्त करने के लिए रिक्त स्थान 'अनपॅक करें। –

+0

अब तक वादा करता है। बेसिक बेंचमार्किंग प्रति-फील्ड सबस्टर्स की एक श्रृंखला दिखाती है और स्ट्रिप ट्रेलिंग रेगेक्स एक अनपैक का उपयोग करने के लिए हमारे लिए लगभग 50% तेज है। टेस्ट पास हो रहे हैं, लेकिन मेरी स्क्रीन पर्लीश चेतावनी से भरी है, इसलिए मैं अभी तक काफी नहीं हूं। –

7

मैंने वास्तव में इस समस्या को बार-बार निपटाया है। Unpack is better than substr

जहां तक ​​रिक्त स्थान रिक्त स्थान जाता है, आप बहुत अधिक खराब हो जाते हैं। वह रेगेक्स हैक इसे करने का "आधिकारिक" तरीका है। आप अपने अनपैक स्टेटमेंट को परिष्कृत करके कुछ दक्षता प्राप्त करने में सक्षम हो सकते हैं (मानते हैं कि कोई डेटा 4 अंकों से अधिक नहीं है, फ़ील्ड के पूर्ण 12 अंकों को अनपैक क्यों करें?), लेकिन अन्यथा, पार्सिंग सिर्फ एक p.i.t.a है।

अपने फ्लैट डेटा के साथ शुभकामनाएँ। फिसलने विरासत जंक, मैं इसे कैसे नफरत करता हूं।

3

क्या आप वाकई इस कार्य पर प्रोसेसर बंधे हैं? गणना इस बात पर संदेह करने के लिए काफी सरल है कि पूरी प्रक्रिया I/O बाध्य होने की संभावना है। किस मामले में तेज़ अनपॅक के लिए अनुकूलित करने से आपको अधिक समय नहीं मिलेगा।

यदि आप वास्तव में प्रोसेसर बाध्य हैं, तो वर्णित समस्या काफी समानांतर लगती है, लेकिन निश्चित रूप से शैतान आपके व्यवसाय की गणना के विवरण में है।

+0

बहुत यकीन है, हाँ। असली कोड में I/O और अनपॅकिंग अलग हो गए हैं, उपरोक्त पॉटेड उदाहरण के विपरीत। समांतरता एक अच्छी कॉल है - हम पहले से ही ऐसा करते हैं। हालांकि अभी भी तारों को तोड़ने पर कम समय बिताना पसंद करेंगे। –

+2

मेरे लिए सबसे बड़ी बाधा डेटाबेस ही है; यदि आप फ्लैट डेटा से निपट रहे हैं, तो आप एक भयानक प्राचीन फ्लैट डेटाबेस से निपट सकते हैं। मुझे अंतराल पर डेटा को आधुनिक डेटाबेस में खींचकर समस्या को हल किया जाता है, लेकिन "वास्तविक समय" डेटा के लिए यह लगभग हमेशा डेटाबेस होता है जो मंदी का कारण बनता है। – Satanicpuppy

+0

सहमत होना है। कुल मिलाकर हमारी प्रक्रिया डाटाबेस में डेटा को अधिकतर समय बिता रही है।हम इसे गति देने के लिए समानांतर प्रक्रियाओं का उपयोग करने में सक्षम हैं। इसने मुझे मारा कि कोड के इतने छोटे हिस्से में 'पर्ल-टाइम' का इतना बड़ा हिस्सा खर्च किया गया था, यहां एक आसान अनुकूलन के लिए दायरा हो सकता है। –

1

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

+0

धन्यवाद। शायद मेरी परियोजना के लिए लाभ अतिरिक्त जटिलता को न्यायसंगत नहीं ठहराएगा। जैसा कि शैतानिकपप्पी ने टिप्पणी की है, इस प्रक्रिया के अन्य भाग हैं जो इससे अधिक महंगे हैं। हालांकि किसी अन्य समस्या के साथ किसी और के लिए काम कर सकता है। –

+3

यदि अधिकांश सीपीयू समय रेगेक्स इंजन और बिल्टिन फ़ंक्शन में बिताया जाता है, तो अधिकांश समय सी भूमि में खर्च किया जाता है (यानी ऑप्ट्री चलने और पर्ल डेटा संरचनाओं को संभालने पर नहीं)। और यह पर्ल वीएम लिखने वाले लोगों को हरा करने के लिए एक अच्छा प्रोग्रामर लेता है। अनपॅक तेज है! – tsee

1

बस इसे समानांतर में जाएं। यह मामूली है, और किसी भी दूरस्थ रूप से आधुनिक मशीन पर यह तेज़ होगा।

0

हमारे कोड के एक सबस्ट्रेट-आधारित संस्करण के बेंचमार्क ने सुझाव दिया कि यह हमारे मौजूदा अनपैक से लगभग 50% तेज हो सकता है। वास्तविक अनुप्रयोग में कोड की तुलना में, सबस्ट्र संस्करण ने हमें रन टाइम में 16% की कमी दी। यह बेंचमार्क और प्रश्न में उल्लिखित प्रोफाइलिंग के आधार पर हम उम्मीद करते हैं।

यह अनुकूलन हमारे लिए उपयोगी हो सकता है। लेकिन, हमारे पास क्षितिज पर एक नए ओएस के लिए माइग्रेशन है, इसलिए हम प्रतीक्षा करेंगे और देखेंगे कि आगे बढ़ने से पहले कोड कैसे प्रदर्शन करते हैं। तुलनात्मक मानकों पर नजर रखने के लिए हमने एक परीक्षण जोड़ा है।

मुहावरा अब हमारे पास है:

$FIELDS::transaction_date = substr($_, 0, 8) || ''; 
$FIELDS::transaction_date =~ s/\s+\z//; 
$FIELDS::customer_id = substr($_, 8, 20) || ''; 
$FIELDS::customer_id =~ s/\s+\z//; 

के रूप में पहले चयनात्मक प्रमुख अंतरिक्ष हटाने के बाद।

अभी तक सभी उत्तरों के लिए धन्यवाद। मैं सिनान को स्वीकार करूंगा क्योंकि यह 'सिर्फ सादा गलत' होने के बावजूद हमारे लिए काम करता है।

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