मेरी तस्वीर की प्रतिक्रिया होती, awkलेकिन अगर आप बहुत सारी लाइनों को संसाधित कर रहे हैं-और मैं लाखों लोगों के बारे में बात कर रहा हूं - तो आप संभवतः "वास्तविक" प्रोग्रामिंग भाषा पर स्विच करने से वास्तविक लाभ देखेंगे।
इसे ध्यान में रखते हुए (और awkपहले से ही एक उत्तर के रूप में लिया जा रहा है) मैंने विभिन्न भाषाओं में कुछ कार्यान्वयन लिखे और पीसीआई-ई एसएसडी पर उसी 10,000-लाइन डेटासेट पर उन्हें बेंचमार्क किया।
me* (C) 0m1.734s
me (C++) 0m1.991s
me (Python/Pypy) 0m2.390s
me (perl) 0m3.024s
Thor+Glenn (sed|sh) 0m3.353s
me (python) 0m3.359s
jasonwryan+Thor (awk) 0m3.779s
rush (while read) 0m6.011s
Thor (sed) 1m30.947s
me (parallel) 4m9.429s
एक नज़र में C सबसे अच्छा दिखता है लेकिन यह उस तेज़ को चलाने के लिए एक सुअर था। PyPy और सी ++ ज्यादा लिखने के लिए आसान कर रहे हैं और प्रदर्शन काफी अच्छी तरह से जब तक आप लाइनों के कई अरबों के बारे में बात कर रहे हैं। अगर ऐसा होता, तो RAM या SSD में यह सब करने के लिए अपग्रेड एक कोड सुधार से बेहतर निवेश हो सकता है।
जाहिर है कि मैंने इनसे गुजरने के समय में शायद सबसे कम विकल्प में कुछ सौ मिलियन रिकॉर्ड संसाधित किए हैं । यदि आप केवल awkलूप या बैश लिख सकते हैं , तो ऐसा करें और जीवन के साथ आगे बढ़ें। मैं स्पष्ट रूप से आज बहुत ज्यादा खाली समय था।
मैंने कुछ बहु-थ्रेडेड विकल्पों (C ++ और पायथन और GNU के साथ संकर parallel) का भी परीक्षण किया था, लेकिन इस तरह के एक सरल ऑपरेशन (स्ट्रिंग विभाजन, लेखन) के लिए किसी भी लाभ से पूरी तरह से धागे के ओवरहेड पूरी तरह से निकल जाते हैं।
पर्ल
awk( gawkयहाँ) ईमानदारी से इस तरह डेटा का परीक्षण करने के लिए कॉल का मेरा पहला बंदरगाह होगा, लेकिन आप पर्ल में काफी समान चीजें कर सकते हैं। समान सिंटैक्स लेकिन थोड़ा बेहतर लेखन हैंडल के साथ।
perl -ane 'open(my $fh, ">", $F[0].".seq"); print $fh $F[1]; close $fh;' infile
अजगर
मुझे पायथन पसंद है। यह मेरी दिन की नौकरी की भाषा है और यह एक अच्छी, ठोस और अविश्वसनीय रूप से पठनीय भाषा है। यहां तक कि एक शुरुआत शायद यह अनुमान लगा सकती है कि यहां क्या हो रहा है।
with open("infile", "r") as f:
for line in f:
id, chunk = line.split()
with open(id + ".seq", "w") as fw:
fw.write(chunk)
आपको यह याद रखना होगा कि आपके वितरण का pythonबाइनरी केवल पायथन का कार्यान्वयन नहीं है। जब मैंने Pypy के माध्यम से इसी परीक्षण को चलाया, तो यह बिना किसी और तर्क अनुकूलन के C से तेज था । पायथन को "धीमी भाषा" के रूप में लिखने से पहले ध्यान रखें।
सी
मैंने यह देखने के लिए इस उदाहरण को शुरू किया कि हम वास्तव में अपने सीपीयू को क्या कर सकते हैं लेकिन स्पष्ट रूप से, सी कोड को एक बुरा सपना है यदि आपने इसे लंबे समय तक नहीं छुआ है। इसमें 100-चार लाइनों तक सीमित होने के अतिरिक्त जोड़ा गया है, हालांकि इसका विस्तार करना बहुत सरल है, मुझे इसकी आवश्यकता नहीं थी।
मेरा मूल संस्करण C ++ और pypy की तुलना में धीमा था, लेकिन इसके बारे में ब्लॉगिंग के बाद मुझे जूलियन क्लोड से कुछ मदद मिली । यह संस्करण अब अपने सबसे तेज़ आईओ बफ़र्स के कारण सबसे तेज़ है। यह किसी भी चीज़ की तुलना में बहुत लंबा और अधिक शामिल है।
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFLEN (8 * 1024)
int main(void) {
FILE *fp;
FILE *fpout;
char line[100];
char *id;
char *token;
char *buf = malloc(BUFLEN);
fp = fopen("infile", "r");
setvbuf ( fp , buf , _IOLBF, BUFLEN );
while (fgets(line, 100, fp) != NULL) {
id = strtok(line, "\t");
token = strtok(NULL, "\t");
char *fnout = malloc(strlen(id)+5);
fnout = strcat(fnout, id);
fnout = strcat(fnout, ".seq");
fpout = fopen(fnout, "w");
setvbuf ( fpout , NULL , _IONBF , 0 );
fprintf(fpout, "%s", token);
fclose(fpout);
}
fclose(fp);
return 0;
}
सी ++
अच्छा प्रदर्शन करता है और वास्तविक सी की तुलना में लिखना बहुत आसान है। आपके पास सभी प्रकार की चीजें हैं जो आपके हाथ को पकड़ती हैं (विशेषकर जब यह तार और इनपुट की बात आती है)। इसका मतलब है कि आप वास्तव में तर्क को सरल बना सकते हैं। strtokसी में एक हॉग है क्योंकि यह पूरे स्ट्रिंग को संसाधित करता है और फिर हमें वह सभी थकाऊ स्मृति आवंटन करने की आवश्यकता है। यह सिर्फ टैब को हिट करने तक लाइन के साथ बहता है और हम सेगमेंट को बाहर खींचते हैं जैसे हमें उनकी आवश्यकता होती है।
#include <fstream>
#include <string>
using namespace std;
int main(void) {
ifstream in("infile");
ofstream out;
string line;
while(getline(in, line)) {
string::size_type tab = line.find('\t', 0);
string filename = line.substr(0, tab) + ".seq";
out.open(filename.c_str());
out << line.substr(tab + 1);
out.close();
}
in.close();
}
जीएनयू समानांतर
(नहीं संस्करण संस्करण)। यह एक अच्छा संक्षिप्त वाक्य-विन्यास है लेकिन OMGSLOW है। मैं इसे गलत उपयोग कर सकता हूं।
parallel --colsep '\t' echo {2} \> {1}.seq <infile
टेस्ट हार्नेस जनरेटर
यहां [ATGC] * 64 की 100000 लाइनों के लिए मेरा डेटा-जनरेटर है। यह तेज़ नहीं है और सुधार बहुत स्वागत योग्य हैं।
cat /dev/urandom | tr -dc 'ATGC' | fold -w 64 | awk 'NR>100000{exit}{printf NR"\t"$0"\n"}' > infile
awkदसियों लाख से कम के लिए अभी भी एक अच्छा जवाब है। यहां तक कि अगर आप [रैखिक रूप से] एक बिलियन लाइनों तक स्केल करते हैं, तो सी केवल आपको 1.5 घंटे पर्ल और 3.6 घंटे से अधिक की बचत कर रहा है।