मेरे पास एक अनूठी स्थिति है जहां मैं इस पृष्ठ पर प्रस्तावित समाधानों को बेंचमार्क कर सकता हूं, और इसलिए मैं इस जवाब को प्रस्तावित समाधानों के समेकन के रूप में लिख रहा हूं, जिनमें प्रत्येक के लिए रन टाइम शामिल है।
सेट अप
मेरे पास 3.261 गीगाबाइट एएससीआईआई पाठ डेटा फ़ाइल है जिसमें प्रति पंक्ति एक कुंजी-मूल्य जोड़ी है। फ़ाइल में कुल 3,339,550,320 पंक्तियाँ हैं और मेरे द्वारा आजमाए गए किसी भी संपादक को खोलने की कोशिश में ख़राबियाँ हैं। मुझे इस फाइल को सब्मिट करने की जरूरत है ताकि कुछ मूल्यों की जांच कर सकूं कि मैंने केवल पंक्ति ~ 500,000,000 के आसपास शुरू की है।
क्योंकि फ़ाइल में बहुत सारी पंक्तियाँ हैं:
- मुझे डेटा के साथ कुछ भी उपयोगी करने के लिए पंक्तियों के केवल सबसेट को निकालने की आवश्यकता है।
- जिन मूल्यों की मुझे परवाह है, उनके लिए हर पंक्ति को पढ़ना एक लंबा समय लेने वाला है।
- यदि समाधान उन पंक्तियों को पढ़ता है जिनकी मुझे परवाह है और शेष फाइल को पढ़ना जारी रखता है तो इससे लगभग 3 बिलियन अप्रासंगिक पंक्तियों को पढ़ने में समय बर्बाद होगा और आवश्यकता से 6x अधिक समय लगेगा।
मेरा सबसे अच्छा मामला परिदृश्य एक समाधान है जो फ़ाइल में से किसी एक पंक्ति को बिना किसी अन्य पंक्तियों को पढ़े फ़ाइल में से निकालता है, लेकिन मैं यह नहीं सोच सकता कि मैं इसे बैश में कैसे पूरा करूंगा।
अपनी पवित्रता के प्रयोजनों के लिए मैं पूर्ण 500,000,000 पंक्तियों को पढ़ने की कोशिश नहीं करने जा रहा हूँ जिनकी मुझे अपनी समस्या के लिए आवश्यकता होगी। इसके बजाय मैं 3,339,550,320 में से 50,000,000 पंक्ति निकालने की कोशिश करूँगा (जिसका अर्थ है कि पूरी फ़ाइल पढ़ने में 60x ज़रूरत से ज़्यादा समय लगेगा)।
मैं timeप्रत्येक कमांड में अंतर्निहित बेंचमार्क का उपयोग करूंगा ।
बेसलाइन
पहले देखते हैं कि कैसे head tailहल करें:
$ time head -50000000 myfile.ascii | tail -1
pgm_icnt = 0
real 1m15.321s
पंक्ति ५० मिलियन के लिए आधार रेखा ००: ०१: १५.३२१ है, अगर मैं सीधे ५०० मिलियन पंक्ति के लिए जाऊं तो यह शायद १२.५ मिनट होगा।
कट गया
मैं इस एक के बारे में संदिग्ध हूँ, लेकिन यह एक शॉट के लायक है:
$ time cut -f50000000 -d$'\n' myfile.ascii
pgm_icnt = 0
real 5m12.156s
इस एक ने 00: 05: 12.156 को चलाने के लिए लिया, जो बेसलाइन की तुलना में बहुत धीमा है! मुझे यकीन नहीं है कि क्या यह पूरी फाइल के माध्यम से पढ़ा गया है या बस रोकने से पहले 50 मिलियन तक लाइन में है, लेकिन इसकी परवाह किए बिना समस्या का एक व्यवहार्य समाधान नहीं लगता है।
AWK
मैंने केवल समाधान के साथ भाग लिया exitक्योंकि मैं पूरी फ़ाइल के चलने की प्रतीक्षा नहीं कर रहा था:
$ time awk 'NR == 50000000 {print; exit}' myfile.ascii
pgm_icnt = 0
real 1m16.583s
यह कोड 00: 01: 16.583 में चला, जो केवल ~ 1 सेकंड धीमा है, लेकिन फिर भी बेसलाइन पर सुधार नहीं हुआ है। इस दर पर अगर बाहर निकलने की आज्ञा को छोड़ दिया गया होता तो शायद पूरी फ़ाइल पढ़ने में लगभग ~ 76 मिनट लग जाते!
पर्ल
मैंने मौजूदा पर्ल समाधान भी चलाया:
$ time perl -wnl -e '$.== 50000000 && print && exit;' myfile.ascii
pgm_icnt = 0
real 1m13.146s
यह कोड 00: 01: 13.146 में चला, जो बेसलाइन की तुलना में ~ 2 सेकंड तेज है। अगर मैं इसे पूर्ण ५००,०००,००० पर चलाऊँ तो शायद १२ मिनट लगेंगे।
sed
बोर्ड पर शीर्ष उत्तर, यहाँ मेरा परिणाम है:
$ time sed "50000000q;d" myfile.ascii
pgm_icnt = 0
real 1m12.705s
यह कोड ००: ०१: १२. ,०५ में चला, जो कि आधार रेखा से ३ सेकंड तेज है, और पर्ल से ०.४ सेकंड अधिक तेज है। अगर मैं इसे पूरी 500,000,000 पंक्तियों पर चलाता तो शायद ~ 12 मिनट लग जाते।
mapfile
मेरे पास 3.1 बैश है और इसलिए मैपफाइल समाधान का परीक्षण नहीं कर सकता है।
निष्कर्ष
ऐसा लगता है, अधिकांश भाग के लिए, head tailसमाधान पर सुधार करना मुश्किल है । सबसे अच्छा sedसमाधान दक्षता में ~ 3% की वृद्धि प्रदान करता है।
(सूत्र के साथ गणना प्रतिशत % = (runtime/baseline - 1) * 100)
पंक्ति 50,000,000
- 00: 01: 12.705 (-00: 00: 02.616 = -3.47%)
sed
- 00: 01: 13.146 (-00: 00: 02.175 = -2.89%)
perl
- 00: 01: 15.321 (+00: 00: 00.000 = + 0.00%)
head|tail
- 00: 01: 16.583 (+00: 00: 01.262 = + 1.68%)
awk
- 00: 05: 12.156 (+00: 03: 56.835 = + 314.43%)
cut
पंक्ति 500,000,000 रु
- 00: 12: 07.050 (-00: 00: 26.160)
sed
- 00: 12: 11.460 (-00: 00: 21.750)
perl
- 00: 12: 33.210 (+00: 00: 00.000)
head|tail
- 00: 12: 45.830 (+00: 00: 12.620)
awk
- 00: 52: 01.560 (+00: 40: 31.650)
cut
पंक्ति 3,338,559,320
- 01: 20: 54.599 (-00: 03: 05.327)
sed
- 01: 21: 24.045 (-00: 02: 25.227)
perl
- 01: 23: 49.273 (+00: 00: 00.000)
head|tail
- 01: 25: 13.548 (+00: 02: 35.735)
awk
- 05: 47: 23.026 (+04: 24: 26.246)
cut
awkऔरsedमुझे यकीन है कि कोई पर्ल वन-लाइनर या साथ ही आ सकता है;)