Le moyen le plus rapide et le plus efficace pour get le nombre d'loggings (lignes) dans un file compressé par gzip

J'essaie de faire un count sur un file gzip de 7,6 Go. J'ai trouvé peu d'approches en utilisant la command zcat .

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

Cela fonctionne mais cela prend trop de time (plus de 10 minutes pour get le count). J'ai essayé quelques autres approches comme

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

Ces trois commands s'exécutent très rapidement mais donnent un nombre incorrect de 28173811.

Comment puis-je effectuer un count dans un minimum de time?

Les commands sed , perl et awk que vous mentionnez peuvent être correctes, mais elles lisent toutes datatables compressées et countnt les caractères de nouvelle ligne. Ces caractères de nouvelle ligne n'ont rien à voir avec les caractères de nouvelle ligne dans datatables non compressées.

Pour countr le nombre de lignes dans datatables non compressées, il n'y a aucun moyen de le décompresser. Votre approche avec zcat est la bonne approche et puisque datatables sont si importantes, il faudra du time pour la décompresser.

La plupart des utilitaires qui traitent de la compression et de la décompression gzip utiliseront probablement les mêmes routines de bibliothèque partagée pour le faire. La seule façon de l'accélérer serait de find une implémentation des routines zlib qui sont en quelque sorte plus rapides que celles par défaut, et rebuild par exemple zcat pour les utiliser.

Utilisez unpigz.

La réponse de Kusalananda est correcte, vous devrez décompresser l'intégralité du file pour scanner son contenu. /bin/gunzip fait aussi vite qu'il le peut, sur un seul kernel. Pigz est une implémentation parallèle de gzip qui peut utiliser plusieurs cœurs.

Malheureusement, la décompression elle-même des files gzip normaux ne peut pas être parallélisée, mais pigz offre une version améliorée de gunzip , unpigz , qui effectue des travaux connexes tels que la lecture, l'écriture et le checksum dans un thread séparé. Dans certains benchmarks rapides, l' unpigz est presque deux fois plus rapide que le gunzip sur ma machine Core i5.

Installez pigz avec votre gestionnaire de packages favori, et utilisez unpigz au lieu de gunzip , ou unpigz -c au lieu de zcat . Alors votre command devient:

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

Tout cela suppose que le CPU est bloqué, pas le disque, bien sûr.

Le problème avec tous les pipelines est que vous doublez essentiellement le travail. Quelle que soit la rapidité de la décompression, datatables doivent encore être apathées vers un autre process.

Perl a PerlIO :: gzip qui vous permet de lire directement les stream gzip. Par conséquent, il pourrait offrir un avantage même si sa vitesse de décompression peut ne pas correspondre à celle d' unpigz :

 #!/usr/bin/env perl use ssortingct; 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]': $!"; 

Je l'ai essayé avec un file compressé gzip de 13 Mo (décompresse à 1,4 Go) sur un vieux MacBook Pro 2010 avec 16 Go de RAM et un vieux ThinkPad T400 avec 8 Go de RAM avec le file déjà dans le cache. Sur le Mac, le script Perl était significativement plus rapide que l'utilisation de pipelines (5 secondes vs 22 secondes), mais sur ArchLinux, il perdait à l'exception de:

  $ time -p ./gzlc.pl spy.gz 
 1154737
 réel 4,49
 user 4,47
 sys 0.01

contre

  $ time -p unpigz -c spy.gz |  wc -l
 1154737
 réel 3,68
 user 4.10
 sys 1,46 

et

  $ time -p zcat spy.gz |  wc -l
 1154737
 réel 6,41
 user 6.08
 sys 0,86 

Clairement, en utilisant unpigz -c file.gz | wc -l unpigz -c file.gz | wc -l est le gagnant ici à la fois en termes de vitesse. Et, cette command line simple bat sûrement l'écriture d'un programme, même court.

La réponse de Kusalananda est la plupart du time correcte. Pour countr les lignes dont vous avez besoin pour searchr des returns à la ligne. Cependant, il est théoriquement possible de searchr des returns à la ligne sans décompresser complètement le file.

gzip utilise la compression DEFLATE. DEFLATE est une combinaison de encoding LZ77 et Huffman. Il peut y avoir un moyen de find le noeud de symbole Huffman pour le saut de ligne et d'ignorer le rest. Il y a presque certainement un moyen de searchr les nouvelles lignes codées en utilisant L277, garder un nombre d'octets et ignorer tout le rest.

Donc, à mon humble avis, il est théoriquement possible de find une solution plus efficace que l'unpigz ou zgrep. Cela étant dit, ce n'est certainement pas pratique (à less que quelqu'un l'ait déjà fait).

Peut être fait en utilisant zgrep avec l' zgrep -c , et le paramètre $ .

Dans ce cas -c, donnez instruction à la command de sortir le nombre de lignes appariées et le regex $ correspond à la fin de la ligne pour qu'il corresponde à chaque ligne ou file.

 zgrep -c $ T.csv.gz 

Comme commenté par @ StéphaneChazelas – zgrep est seulement un script autour de zcat et grep et il devrait fournir des performances similaires à la suggestion originale de zcat | wc -l zcat | wc -l

Comme vous pouvez le voir, la plupart des réponses essaient d'optimiser ce qu'il peut: le nombre de changements de context et d'inputs-sorties inter-process. La raison en est, c'est le seul que vous pouvez optimiser ici facilement.

Maintenant, le problème est que son besoin en ressources est presque négligeable pour le besoin en ressources de la décompression. C'est pourquoi les optimizations ne vont pas vraiment faire plus vite.

Là où il pourrait être vraiment accéléré, il s'agirait d'un algorithm un-gzip (c'est-à-dire décompression) modifié, qui exclut la production réelle du stream de données décompressé; au lieu de cela, il calcule uniquement le nombre de lignes nouvelles dans le stream décompressé par rapport au stream compressé . Ce serait difficile, cela nécessiterait une connaissance approfondie de l'algorithm de gzip (une combinaison des algorithms de compression LZW et Huffman ). Il est tout à fait probable que l'algorithm ne permette pas d'optimiser significativement le time de décompression avec l'éclaircissement, qu'il suffit de connaître le nombre de nouvelles lignes. Même si cela serait possible, une nouvelle librairie de décompression gzip aurait dû être développée (elle n'existe pas jusqu'à ce qu'on sache).

La réponse réalist à votre question est que non, vous ne pouvez pas le faire beaucoup plus rapidement.

Peut-être que vous pourriez utiliser une décompression gzip en parallèle, s'il existe. Il pourrait utiliser plusieurs cœurs de processeur pour la décompression. S'il n'existe pas, il pourrait être relativement facile à développer.

Pour le xz , il existe un compresseur parallèle (pxz).