एक बड़ी फ़ाइल पर grepping के लिए प्रदर्शन में सुधार


10

मेरे पास FILE_A है जिसमें 300,000 से अधिक लाइनें हैं और FILE_B जिसकी 30 मिलियन से अधिक लाइनें हैं। मैंने एक Bash स्क्रिप्ट बनाई जो FILE_A में FILE_A पर प्रत्येक पंक्ति को greps बनाती है और एक नई फ़ाइल के लिए grep का परिणाम लिखती है।

इस पूरी प्रक्रिया में 5 घंटे का समय लग रहा है।

मैं अपनी स्क्रिप्ट के प्रदर्शन में सुधार कैसे कर सकता हूं?

मैं grep -F -m 1grep कमांड के रूप में उपयोग कर रहा हूं । FILE_A इस तरह दिखता है:

123456789 
123455321

और FILE_B इस तरह है:

123456789,123456789,730025400149993,
123455321,123455321,730025400126097,

तो बैश के साथ मेरे पास एक whileलूप है जो कि FILE_A में अगली पंक्ति को चुनता है और इसे FILE_B में जमा करता है। जब पैटर्न FILE_B में मिलता है, तो मैं इसे result.txt फ़ाइल में लिखता हूं।

while read -r line; do
   grep -F -m1 $line 30MFile
done < 300KFile

जवाबों:


17

प्रयोग करके देखें grep --file==FILE_A। यह निश्चित रूप से पैटर्न को मेमोरी में लोड करता है, जिसका अर्थ है कि यह केवल FILE_B को एक बार स्कैन करेगा।

grep -F -m1 --file==300KFile 30MFile

यह केवल यह मानकर काम करेगा कि मेरे पास पर्याप्त मेमोरी है?
रोगरियो_मारियो

ईमानदारी से, मैंने खुद को उस आकार की फ़ाइलों पर आज़माया नहीं है, लेकिन मेरा मानना ​​है कि इसे नाटकीय रूप से आपकी गति में सुधार करना चाहिए। यदि आप एक आधुनिक मशीन पर हैं, तो आपको मेमोरी में 300K फाइल रखने में कोई परेशानी नहीं होनी चाहिए। (या उस मामले के लिए एक 30 एम।)
रोबोट

जब मैंने -f (--file) विकल्प का उपयोग किया था तो यह मूल रूप से 30MFile को फिर से बनाए। क्या मुझसे कुछ गलत हो रही है?
रोगरियो_मारियो

हम्म् ... शायद 300Kfile में एक खाली लाइन थी?
रोबोट

सही मौके पर! वह यह था! यह पूरी तरह से काम किया, यह 30 सेकंड में समाप्त हो गया! धन्यवाद!!
रोगरियो_मारियो

2

यहाँ पोस्टर्लिटी के लिए एक पर्ल उत्तर दिया गया है। मैं नियमित रूप से 1M लाइनों को 30-35M लाइनों के मिलान के लिए करता हूं। इसे खत्म होने में लगभग 10 सेकंड का समय लगता है।

सबसे पहले, FILE_A को हैश करें:

my %simple_hash;
open my $first_file, '<', 'FILE_A' or die "What have you done?! $!";
while (<$first_file>) {
  chomp;                 ## Watch out for Windows newlines
  $simple_hash{$_} = 1;  ## There may be an even faster way to define this
}
close $first_file;

फिर, यदि आपकी बड़ी फ़ाइल सीमांकित है और पता है कि किस कॉलम के बाद जाना है, तो हैश कुंजी के अस्तित्व की जांच करें क्योंकि आप FILE_B नीचे जाते हैं, जो कि समानता या नियमित अभिव्यक्ति मिलान के लिए जाँच करने की तुलना में बहुत तेज़ है:

open my $second_file, '<', 'FILE_B' or die "Oh no, not again.. $!";
while (<$second_file>) {
  my ($col1, undef) = split ',';
  if (exists($simple_hash{$col1}) {
    print $_;
  }
}
close $second_file;

यदि आपकी बड़ी लक्ष्य फ़ाइल अच्छी तरह से पार्स-सक्षम नहीं है, तो यह स्क्रिप्ट अपना मूल्य खो देती है, क्योंकि इसकी गति इतनी होती है कि नियमित अभिव्यक्ति इंजन में आग नहीं लगती है ।


1

यदि आपको कुछ और शामिल प्रोग्रामिंग से एतराज नहीं है, तो प्रत्यय के पेड़ों (या एक प्रकार) का उपयोग करने पर विचार करें ।

आप रैखिक समय में उककोन के एल्गोरिथ्म काFILE_B उपयोग करके प्रीप्रोसेस कर सकते हैं । फिर, आप प्रत्येक लाइन को लाइन लाइन में समय रेखीय में क्वेरी करते हैं और सभी पंक्ति संख्याओं को मिलाते हैं जो मेल खाते हैं (पेड़ को एक टैड को अनुकूलित करने की आवश्यकता हो सकती है) जिसे आप एक परिणाम फ़ाइल में लिख सकते हैं।FILE_A

पूरी प्रक्रिया समय में चलती है O (n + Nm) यदि n की लंबाई है FILE_B, Nतो लाइनों की संख्या है FILE_Aऔर m सबसे लंबी रेखा की लंबाई है FILE_A- यह अनिवार्य रूप से रैखिक रनटाइम है। परिमाण द्वारा आपके मूल दृष्टिकोण को द्विघात समय पर धड़कता है।


1

मैंने --mmapझंडे को हाल ही में पाया , इसका परीक्षण करने का मौका नहीं मिला, लेकिन मुझे आपके निष्कर्षों के बारे में सुनकर खुशी होगी। यहाँ मैन पेज से विवरण है:

--mmap If  possible, use the mmap(2) system call to read input, instead
      of the default read(2) system call.  In some situations,  --mmap
      yields  better performance.  However, --mmap can cause undefined
      behavior (including core dumps) if an input file  shrinks  while
      grep is operating, or if an I/O error occurs.

देखें इस या इस बारे में अधिक जानकारी के लिए mmap


मैं निश्चित रूप से इसे एक शॉट देने जा रहा हूं और मैं आपको बता दूंगा कि यह कैसे चलता है। कितना संभावित है कि मैं एक कोर डंप का सामना करूंगा?
रोगरियो_मारियो

@rogerio_marcio खैर, जैसा कि मैं उस आदमी को समझता हूं, "अगर grep काम करते समय फ़ाइल सिकुड़ जाती है, या यदि I / O त्रुटि होती है।" वास्तव में शायद नहीं, लेकिन आपको यह बेहतर पता होना चाहिए। (अगर मुझे लगता है कि grep के दौरान फाइल अछूती है - ऐसा नहीं होना चाहिए)
रामजी कहिल

उस --mmapखुराक का परीक्षण करने के लिए, जो कुछ भी डंप नहीं करता है, मैं उसके साथ एक रन की सिफारिश करूंगा --mmap, और एक के बिना। और फिर wcयह देखने के लिए उपयोग करें कि आपके पास आउटपुट की समान मात्रा है - यह एक मजबूत परीक्षण होना चाहिए यह देखते हुए कि हम 2 बार grep भाग गए, और बस एक झंडा अलग हो गया।
रामजी कहिल

@rogerio_marcio क्या आपने यह कोशिश की है? कोई अंतर्दृष्टि?
रामजी कहिल

-1

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


आप सभी अन्य उत्तरों के साथ डेटाबेस व्हील को
सुदृढ़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.