सबसे तेज़ और सबसे कुशल तरीका है कि गज़िप-संपीड़ित फ़ाइल में रिकॉर्ड (पंक्तियाँ) की संख्या प्राप्त करें


16

मैं एक 7.6 GB gzip फ़ाइल पर रिकॉर्ड गणना करने की कोशिश कर रहा हूं। मुझे zcatकमांड का उपयोग करते हुए कुछ दृष्टिकोण मिले ।

$ zcat T.csv.gz | wc -l
423668947

यह काम करता है लेकिन इसमें बहुत अधिक समय (गिनती प्राप्त करने में 10 मिनट से अधिक) लगता है। मैंने कुछ और तरीकों की कोशिश की

$ sed -n '$=' T.csv.gz
28173811
$ perl -lne 'END { print $. }' < T.csv.gz
28173811
$ awk 'END {print NR}' T.csv.gz
28173811

इन तीनों आदेशों को बहुत तेजी से क्रियान्वित किया जा रहा है, लेकिन 28173811 की गलत गणना है।

मैं न्यूनतम समय में रिकॉर्ड गणना कैसे कर सकता हूं?


5
आपको रिकॉर्ड की संख्या गिनने की आवश्यकता क्यों है? यदि आप उन्हें संसाधित करने से पहले उन्हें गिनने का प्रयास कर रहे हैं, तो इसका मतलब है कि आपको फ़ाइल को दो बार खोलना होगा।
एंड्रयू हेनले

3
आप ऐसा क्यों कर रहे हैं, इस बारे में अधिक जानकारी उपयोगी होगी। यदि यह कुछ चल रहा है - अर्थात्, आप नियमित रूप से फ़ाइलों का एक गुच्छा सेक करते हैं, और कुछ समय बाद रिकॉर्ड की संख्या जानने की आवश्यकता होती है - क्यों न उन्हें संकुचित किया जाए, और फ़ाइल नाम में नंबर एम्बेड करें?
jamesqf

3
मैकेनिकल डिस्क से 9.7GB फ़ाइल पढ़ना स्वाभाविक रूप से धीमा है। SSD पर फ़ाइल संग्रहीत करें, और देखें कि कितनी तेज़ गनज़िप / zcat चलती है। लेकिन जैसा @jamesqf कहते हैं, फ़ाइलनाम में linecount स्टोर करें, या tgz में एक फ़ाइल में, और उस फ़ाइल को निकालना बहुत तेज़ होगा।
च्च्कॉट्रिल

2
ऐसे अच्छे सैद्धांतिक कारण हैं कि आप इस काम से बच नहीं सकते। एक संपीड़न प्रारूप जो आपको डेटा की कुछ उपयोगी संपत्ति निर्धारित करने देता है "इसे डिकॉम्प्रेसिंग के बिना" परिभाषा से बहुत अधिक है एक संपीड़न प्रारूप जितना अच्छा नहीं हो सकता है :)
hobbs

जवाबों:


29

sed, perlऔर awkआदेश दिए गए हैं उल्लेख सही हो सकता है, लेकिन वे सभी को पढ़ने के संकुचित है कि में डेटा और मायने रखता है newline अक्षर। इन न्यूलाइन वर्णों का असम्पीडित डेटा में न्यूलाइन वर्णों से कोई लेना-देना नहीं है।

असम्पीडित डेटा में लाइनों की संख्या की गणना करने के लिए, इसे अनलॉक्ड करने का कोई तरीका नहीं है। के साथ अपने दृष्टिकोण zcatसही दृष्टिकोण है और के बाद से डेटा इतनी बड़ी है, यह होगा उसे असंपीड़ित करने में समय लगता है।

अधिकांश उपयोगिताओं जो gzipसंपीड़न और विघटन से निपटती हैं, सबसे अधिक संभावना है कि ऐसा करने के लिए एक ही साझा पुस्तकालय दिनचर्या का उपयोग करें। इसे गति देने का एकमात्र तरीका zlibदिनचर्या के कार्यान्वयन को ढूंढना होगा जो किसी भी तरह डिफ़ॉल्ट लोगों की तुलना में तेज़ हैं, और zcatउन लोगों का उपयोग करने के लिए उदाहरण के लिए पुनर्निर्माण करें।


11
यह एक गैर-तुच्छ प्रोग्रामिंग अभ्यास होगा, लेकिन संभव है। पूरे बिंदु का पुनर्निर्माण नहीं करना है zcat। के काम का एक महत्वपूर्ण हिस्सा zcatवास्तविक आउटपुट उत्पन्न करना है। लेकिन अगर आप केवल \nपात्रों की गिनती कर रहे हैं , तो यह आवश्यक नहीं है। gzipसंपीड़न अनिवार्य रूप से छोटे तारों द्वारा आम लंबे तारों को बदलने के द्वारा काम करता है। तो आपको केवल शब्दकोश में लंबे तार के बारे में परवाह करने की आवश्यकता है जिसमें एक है \n, और उन लोगों की घटना (भारित) की गणना करें। अंग्रेजी नियमों के कारण, .\nएक आम 16 बिट्स स्ट्रिंग है।
MSalters

19

Unpigz का उपयोग करें।

कुसलानंद का जवाब सही है, आपको इसकी सामग्री को स्कैन करने के लिए उस पूरी फाइल को अनकैप्ड करना होगा/bin/gunzipयह एक ही कोर पर के रूप में उपवास के रूप में यह करता है। पिगज़ एक समानांतर कार्यान्वयन है gzipजो कई कोर का उपयोग कर सकता है।

दुख की बात है, सामान्य gzip फ़ाइलों के विसंपीड़न ही parallelized नहीं किया जा सकता है, लेकिन pigzप्रस्ताव के एक उन्नत संस्करण करता है gunzip, unpigzकि इस तरह, पढ़ने लिखने, और एक अलग थ्रेड में checksumming के रूप में संबंधित काम करता है। कुछ त्वरित बेंचमार्क में, मेरे कोर i5 मशीन पर unpigzलगभग दोगुना है gunzip

pigzअपने पसंदीदा पैकेज मैनेजर के साथ स्थापित करें , और unpigzइसके बजाय gunzip, या के unpigz -cबजाय का उपयोग करें zcat। तो आपकी आज्ञा बन जाती है:

$ unpigz -c T.csv.gz | wc -l

यह सब मानता है कि टोंटी सीपीयू है, डिस्क नहीं, बिल्कुल।


4
मेरा pigzमैन पेज बताता है कि Decompression को समानांतर नहीं किया जा सकता है, कम से कम उस उद्देश्य के लिए विशेष रूप से तैयार किए गए विरल धाराओं के बिना नहीं। नतीजतन, पिगज़ विसंपीड़न के लिए एक एकल थ्रेड (मुख्य धागा) का उपयोग करता है, लेकिन पढ़ने, लिखने और गणना की जांच के लिए तीन अन्य धागे बनाएगा, जो कुछ परिस्थितियों में विघटन को गति दे सकता है । फिर भी, आप की तरह मुझे लगता है कि यह कम से कम दोगुना है gzip, अगर समानता की वजह से नहीं है
स्टीफन चेज़लस

@ स्टीफनचेलजेलस अच्छी बात! कि विघटित करने के लिए हल्के निराशाजनक स्पीडअप की व्याख्या करता है। मैंने इस जानकारी को बेहतर ढंग से दर्शाने के लिए अपनी पोस्ट को संपादित किया।
मार्सेलम

5

सभी पाइपलाइनों के साथ समस्या यह है कि आप अनिवार्य रूप से काम को दोगुना कर रहे हैं। कोई फर्क नहीं पड़ता कि कितनी तेजी से विघटन हो रहा है, डेटा को अभी भी दूसरी प्रक्रिया में बंद करने की आवश्यकता है।

Perl में PerlIO :: gzip है जो आपको सीधे gzipped स्ट्रीम पढ़ने की अनुमति देता है। इसलिए, यह एक लाभ की पेशकश कर सकता है भले ही इसकी विघटन की गति से मेल न खाए unpigz:

#!/usr/bin/env perl

use strict;
use warnings;

use autouse Carp => 'croak';
use PerlIO::gzip;

@ARGV or croak "Need filename\n";

open my $in, '<:gzip', $ARGV[0]
    or croak "Failed to open '$ARGV[0]': $!";

1 while <$in>;

print "$.\n";

close $in or croak "Failed to close '$ARGV[0]': $!";

मैंने इसे एक पुराने 2010 मैकबुक प्रो पर 13 एमबी रैम और एक पुराने थिंकपैड T400 के साथ 8 जीबी रैम के साथ पहले से कैश में पहले से ही 13 एमबी की गज़िप संपीड़ित फ़ाइल (1.4 जीबी तक डिकॉम्प्रेस) के साथ आज़माया । मैक पर, पर्ल स्क्रिप्ट पाइपलाइनों का उपयोग करने की तुलना में काफी तेज थी (5 सेकंड बनाम 22 सेकंड), लेकिन आर्चलिनक्स पर, यह अनपीग से हार गया:

$ समय -p ./gzlc.pl spy.gz 
1154737
असली 4.49
उपयोगकर्ता 4.47
sys 0.01

बनाम

$ समय -p unpigz -c spy.gz | wc -l
1154737
वास्तविक 3.68
उपयोगकर्ता 4.10
सीस 1.46

तथा

$ समय -p zcat spy.gz | wc -l
1154737
असली 6.41
उपयोगकर्ता 6.08
सीस 0.86

जाहिर है, unpigz -c file.gz | wc -lगति के संदर्भ में दोनों का उपयोग करना यहां विजेता है। और, यह सरल कमांड लाइन निश्चित रूप से एक प्रोग्राम लिखने के लिए धड़कता है, हालांकि कम है।


1
मुझे लगता है कि आप दो प्रक्रियाओं के बीच डेटा को स्थानांतरित करने के लिए आवश्यक संसाधनों को बहुत कम कर रहे हैं, विघटन गणना की तुलना में। ); विभिन्न दृष्टिकोण बेंचमार्किंग प्रयास करें
marcelm

2
@ Sinan Linuxnür मेरे x86_64 लिनक्स सिस्टम (पुराने हार्डवेयर पर) gzip | wcमें आपकी पर्ल स्क्रिप्ट की तुलना में समान गति है। और pigz | wcउपवास से दोगुना है। gzipउसी गति से चलता है, भले ही मैं आउटपुट को / dev / null या पाइप में लिखता हूं, wcजो मुझे विश्वास है कि पर्ल द्वारा उपयोग की जाने वाली "gzip लाइब्रेरी" gzip कमांड लाइन टूल से तेज है। शायद पाइप के साथ एक और मैक / डार्विन विशिष्ट समस्या है। यह अभी भी आश्चर्यजनक है कि यह पर्ल संस्करण प्रतिस्पर्धी है।
रुडाइमियर

1
मेरे x86_64 लिनक्स पर, यह लगता है कि इससे बेहतर zcatऔर बुरा है unpigz। मैं चकित हूं कि मैक की तुलना में लिनक्स सिस्टम पर पाइप लाइन कितनी तेज है। मैं यह उम्मीद नहीं कर रहा था, भले ही मुझे जैसा होना चाहिए था मैंने एक बार उसी प्रोग्राम को सीपीयू सीमित लिनक्स वीएम पर उसी मैक पर तेजी से दौड़ाया जो नंगे धातु पर था।
सिनान Maynür

1
यह तो दिलचस्प है; मेरे सिस्टम पर (डेबियन 8.8 am6464, क्वाड कोर i5), पर्ल स्क्रिप्ट थोड़ी धीमी है ... 109M .gz फाइल 1.1G पाठ के लिए विघटित होती है, लगातार 5.4 सेकेंड लेती है zcat | wc -l, और आपकी प्रति लिपि के लिए 5.5 सेकेंड लेती है । ईमानदारी से, मैं भिन्नता से चकित हूं कि लोग यहां रिपोर्ट कर रहे हैं, खासकर लिनक्स और मैकओएस एक्स के बीच!
मार्सेलम

मुझे नहीं पता कि अगर मैं अपने मैक पर जो देख रहा हूं उसे सामान्य कर सकता हूं, तो कुछ अजीब हो रहा है। विघटित 1.4 जीबी फ़ाइल के साथ, wc -l2.5 सेकंड लगते हैं। gzcat compressed.gz > /dev/null2.7 सेकंड लेता है। फिर भी, पाइपलाइन को 22 सेकंड लगते हैं। अगर मैं जीएनयू की कोशिश करता हूं wc, तो विघटित फ़ाइल पर केवल आधा सेकंड लगता है, लेकिन पाइपलाइन में 22 सेकंड। जीएनयू zcatको निष्पादित होने में दोगुना समय लगता है zcat compressed.gz > /dev/null। यह मावेरिक्स, पुराने कोर 2 डुओ सीपीयू, 16 जीबी रैम, क्रूसिकल एमएक्स 100 एसएसडी पर है।
सिनान Maynür

4

कुसलानंद का जवाब ज्यादातर सही है। लाइनों को गिनने के लिए आपको नई ख़ूबियों की तलाश करनी होगी। हालाँकि यह पूरी तरह से फ़ाइल को बिना नए सिरे से खोजने के लिए सैद्धांतिक रूप से संभव है।

gzip DEFLATE कम्प्रेशन का उपयोग करता है। DEFLATE LZ77 और हफ़मैन एन्कोडिंग का एक संयोजन है। हो सकता है कि न्यूलाइन के लिए हफ़मैन प्रतीक नोड का पता लगाने और बाकी को अनदेखा करने का एक तरीका हो। लगभग निश्चित रूप से L277 का उपयोग करके एन्कोड किए गए नए समाचारों को देखने का एक तरीका है, एक बाइट काउंट रखें और बाकी सब को अनदेखा करें।

तो IMHO अपने सैद्धांतिक रूप से एक समाधान के साथ आने के लिए संभव है जो अप्रकाशित या zgrep से अधिक कुशल हो। कहा जा रहा है कि यह निश्चित रूप से व्यावहारिक नहीं है (जब तक कि किसी ने पहले ही ऐसा नहीं किया है)।


7
इस विचार के साथ एक बड़ी समस्या यह है कि DEFLATE द्वारा उपयोग किए जाने वाले हफ़मैन प्रतीक LZ77 संपीड़न के बाद बिट अनुक्रमों के अनुरूप हैं , इसलिए उनके और U + 000A वर्णों के बीच असम्पीडित फ़ाइल में कोई साधारण संबंध नहीं हो सकता है। उदाहरण के लिए, शायद एक हफमैन प्रतीक का अर्थ है "के अंतिम पांच बिट्स।" "\ n" के पहले तीन बिट्स के बाद, और दूसरे प्रतीक का मतलब "टी" के सभी आठ बिट्स के बाद "\ n" के अंतिम पांच बिट्स हैं।
zwol

@zwol नहीं, Deflate एल्गोरिथ्म का LZ77 हिस्सा बाइट अनुक्रमों को संपीड़ित करता है, न कि थोड़ा सा अनुक्रम। en.wikipedia.org/wiki/DEFLATE#Duplicate_string_elimination
रॉस रिज

1
@RossRidge हुह, मुझे यह नहीं पता था, लेकिन मुझे नहीं लगता कि मैंने जो कहा था, उसे अमान्य कर दिया। Huffman प्रतीकों कर सकते हैं, यह है कि संदर्भ के अगले अनुच्छेद के आधार पर मुझे ऐसा लगता है, प्रत्येक बिट के परिवर्तनशील का विस्तार, वे बाइट्स की एक पूरी संख्या का उत्पादन करने की जरूरत नहीं है।
zwol

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

1

ध्वज, और पैरामीटर के zgrepसाथ उपयोग किया जा सकता है ।-c$

इस स्थिति में -c को निर्देश देता है कि मैच की गई लाइनों की संख्या और रेगेक्स $ लाइन के अंत तक आउटपुट करें ताकि यह हर लाइन या फाइल से मेल खाए।

zgrep -c $ T.csv.gz 

@ StéphaneChazelas द्वारा टिप्पणी की के रूप में - zgrepकेवल एक स्क्रिप्ट के आसपास है zcatऔर grepऔर यह मूल सुझाव के इसी तरह के प्रदर्शन प्रदान करना चाहिएzcat | wc -l


2
हाय यारोन इस जवाब के लिए भी धन्यवाद zgrep जितना समय लग रहा है zcat के रूप में मुझे कुछ और दृष्टिकोण खोजने की आवश्यकता है
राहुल

8
zgrepआम तौर पर एक स्क्रिप्ट होती है जो डेटा को अनलॉक्ड करने के लिए zcat(उसी के रूप में gzip -dcq) इनवॉइस करती है और उसे फीड करती है grep, इसलिए मदद करने वाली नहीं है।
स्टीफन चेज़लस

1
@ स्टीफनचेज़ेलस - टिप्पणी के लिए धन्यवाद, इसे प्रतिबिंबित करने के लिए मेरे उत्तर को अपडेट करें।
Yaron

0

जैसा कि आप देख सकते हैं, अधिकांश उत्तर यह अनुकूलित करने की कोशिश करते हैं: संदर्भ स्विच की संख्या और अंतर-प्रक्रिया IO। कारण यह है, कि केवल यही है जिसे आप यहाँ आसानी से अनुकूलित कर सकते हैं।

अब समस्या यह है कि इसकी संसाधन की आवश्यकता लगभग अपघटन की संसाधन आवश्यकता के लिए नगण्य है। यही कारण है कि अनुकूलन वास्तव में कुछ भी तेजी से नहीं होगा।

जहाँ इसे वास्तव में त्वरित किया जा सकता है, यह एक संशोधित अन-जीज़िप (यानी डीकोप्रेशन) एल्गोरिथ्म होगा, जो विघटित डेटा स्ट्रीम के वास्तविक उत्पादन को छोड़ देता है; बल्कि यह केवल संपीड़ित एक से विघटित धारा में न्यूलाइन्स की संख्या की गणना करता है । यह कठिन होगा, इसे गज़िप के एल्गोरिथ्म ( एलजेडडब्ल्यू और हफ़मैन संपीड़न एल्गोरिदम के कुछ संयोजन ) के गहन ज्ञान की आवश्यकता होगी । यह काफी संभावना है, कि एल्गोरिथ्म प्रकाश के साथ विघटन समय को महत्वपूर्ण रूप से अनुकूलित करना संभव नहीं बनाता है, कि हमें केवल नई रेखाओं को जानना होगा। यहां तक ​​कि अगर यह संभव होगा, तो अनिवार्य रूप से एक नया जीज़िप डिकम्प्रेसन लाइब्रेरी विकसित किया जाना चाहिए था (यह तब तक मौजूद नहीं है जब तक पता नहीं है)।

आपके प्रश्न का यथार्थवादी उत्तर यह है कि नहीं, आप इसे बहुत तेज नहीं बना सकते।

हो सकता है कि आप कुछ समानांतर gzip अपघटन का उपयोग कर सकते हैं, अगर यह मौजूद है। यह विघटन के लिए कई सीपीयू कोर का उपयोग कर सकता है। यदि यह मौजूद नहीं है, तो यह अपेक्षाकृत आसानी से विकसित हो सकता है।

के लिए XZ , वहाँ एक समानांतर कंप्रेसर (pxz) मौजूद है।

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