Le moyen le plus rapide pour battre des lignes dans un fichier sous Linux
Je veux battre un gros fichier avec des millions de lignes de chaînes dans Linux. J'ai essayé 'tri -R' Mais elle est très lente (compter 50 minutes pour une 16M gros fichier). Est-il plus rapide de l'utilitaire que je peux utiliser à la place de?
Chouf? en.wikipedia.org/wiki/Shuf
des millions de lignes de 16 mo pour un fichier: vous avez de très courtes lignes? BTW: 16 MO n'est pas grand. Il rentre dans le coeur, et le tri prend moins d'une seconde, je suppose.
Quelle est l'entropie Shuf introduit? Est-il aussi aléatoire qu' 'tri -R'
Oh...ses 16 Millions de ligne de fichier, pas de 16 MO. Le tri est assez rapide sur ce dossier, mais de tri -R' est très lent.
Je suppose que c'est
des millions de lignes de 16 mo pour un fichier: vous avez de très courtes lignes? BTW: 16 MO n'est pas grand. Il rentre dans le coeur, et le tri prend moins d'une seconde, je suppose.
Quelle est l'entropie Shuf introduit? Est-il aussi aléatoire qu' 'tri -R'
Oh...ses 16 Millions de ligne de fichier, pas de 16 MO. Le tri est assez rapide sur ce dossier, mais de tri -R' est très lent.
Je suppose que c'est
/dev/random
. Vous pouvez contrôler ensuite l'entropie de la source avec --random-source
.OriginalL'auteur alpha_cod | 2013-02-06
Vous devez vous connecter pour publier un commentaire.
Utilisation
shuf
au lieu desort -R
(page de man).La lenteur de
sort -R
est probablement en raison de hachage de chaque ligne.shuf
juste fait une permutation aléatoire de sorte qu'il n'a pas ce problème.(Ce qui a été suggéré dans un commentaire, mais pour une raison pas écrit comme une réponse par personne)
shuf
charge tout en mémoire, tout fichier est trop gros pour charger dans la mémoire échoue. Pas un problème en soi, mais si vous essayez de faire cela avec la pièce de théâtre de gros fichiers.OriginalL'auteur dshepherd
50 minutes n'est pas causée par les mécanismes de tri, en fonction de votre description. Le temps passé à attendre les
/dev/random
pour générer suffisamment d'entropie.Une approche consiste à utiliser une source externe de données aléatoires (http://random.org, par exemple) avec une variation sur un Schwartzian Transformer. Le Schwartzian Transformer transforme les données à trier dans "enrichi" de données avec la clé de tri embarqué. Les données sont triées à l'aide de la touche puis la touche est jeté.
Pour l'appliquer à votre problème:
de générer un fichier texte avec des nombres aléatoires, 1 par ligne, avec le même nombre de lignes que le fichier afin d'être triés. Cela peut être fait à tout moment, exécuter en arrière-plan, exécuter sur un serveur différent, téléchargés à partir de random.org, etc. Le point est que ce hasard n'est pas généré pendant que vous essayez de faire le tri.
créer une version enrichie du fichier à l'aide
paste
:paste random_number_file.txt string_data.txt > tmp_string_data.txt
trier ce fichier:
sort tmp_string_data.txt > sorted_tmp_string_data.txt
supprimer les données aléatoires:
cut -f2- sorted_tmp_string_data.txt > random_string_data.txt
C'est l'idée de base. Je l'ai essayé et il fonctionne, mais je n'ai pas de 16 millions de lignes de texte ou de 16 millions de lignes de nombres aléatoires. Vous pouvez pipeline certaines de ces étapes au lieu de sauver tout le disque.
sort -R
(vs 4 secondes avecshuf
). Si elle a été en attente pour plus d'entropie alors que l'utilisation du processeur serait minime, non?OriginalL'auteur Paul Miller
Vous pouvez essayer mon outil: HugeFileProcessor. Il est capable de mélanger les fichiers de centaines de Sgb dans un délai raisonnable.
Voici les détails sur le brassage de la mise en œuvre. Il nécessite de spécifier batchSize - nombre de lignes à garder en mémoire lors de l'écriture à la sortie. Le plus est le mieux (à moins que vous êtes hors de RAM), que le total de brassage des temps serait (nombre de lignes dans sourceFile) /batchSize * (le temps de bien lire sourceFile). Veuillez noter que le programme mélange sur l'ensemble du fichier, pas sur par lot.
L'algorithme est le suivant.
Compter les lignes dans sourceFile. Cela se fait simplement par la lecture de tout fichier ligne par ligne. (Voir quelques comparaisons ici.) Cela donne également une mesure de combien de temps cela prendrait-il pour lire tout le fichier une fois. Donc, on peut estimer combien de temps il faudrait pour effectuer une lecture aléatoire, car cela exigerait Ceil(linesCount /batchSize) dossier complet lit.
Comme nous le savons maintenant, le total linesCount, on peut créer un index de tableau de linesCount taille et mélangez à l'aide De Fisher–Yates (appelé orderArray dans le code). Ce serait de nous donner l'ordre dans lequel nous voulons lignes dans un mélangées fichier. Notez que c'est un ordre global sur l'ensemble du fichier, et non par lot ou chunk ou quelque chose.
Maintenant le code réel. Nous avons besoin d'obtenir toutes les lignes de sourceFile dans un ordre nous venons de calculer, mais on ne peut pas lire tout le fichier en mémoire. Nous avons donc simplement diviser la tâche.
Pourquoi ça marche?
Parce que tout ce que nous faisons est juste de la lecture du fichier source à partir de début à la fin. Ne cherche avant/arrière, et c'est ce que les disques Durs comme. Le fichier est lu en morceaux selon le disque dur interne tampons, FS blocs, CPU cahce, etc. et tout est en train de lire dans l'ordre.
Quelques chiffres
Sur ma machine (Core i5, 16 GO de RAM, Win8.1, disque dur Toshiba DT01ACA200 2 TO, NTFS) j'ai été capable de mélanger un fichier de 132 GO (84 000 000 de lignes) en environ 5 heures en utilisant batchSize de 3 500 000. Avec batchSize de 2 000 000 il a fallu environ 8 heures. Vitesse de lecture était d'environ 118000 lignes par seconde.
OriginalL'auteur Mikhail