Lorsque l’on analyse des logs serveur, il est fréquent de devoir dé-dupliquer de très gros fichiers.
A titre d’exemple, j’ai eu besoin récemment de dé-dupliquer un fichier de 51 millions de lignes (1,4 Go).
Avec Excel, cela semble compromis… (je n’ai pas essayé cela dit ^^).
Sur une console Linux, c’est très facile, on trie puis on déduplique
sort fichier.txt | uniq > fichier.dedup.txt |
Cela fait le job, mais c’est un peu lent (12 minutes et 21 secondes sur ma machine).
Le principal défaut de cette commande, c’est qu’il y a un unique processus et donc l’utilisation d’un seul coeur du processeur. Un peu dommage puisque que j’en ai deux sur ma machine.
Heureusement, Linux est un modèle de modularité.
En quelques lignes de script shell, on peut parralléliser le traitement et faire une sorte de MapReduce (très à la mode en ce moment).
split -l 1000000 urls.txt urls.split. for file in ls urls.split.* do sort $file > $file.sorted & done wait sort -m *.sorted | uniq > urls.sorted.txt.2 |
Le principe est simple, on découpe notre gros fichier en plusieurs fichiers. Chaque fichier va être trié en parallèle via des processus distincts. Une fois trié, on merge et on dé-duplique.
On augmente le nombre d’écritures sur le disque, mais on obtient une utilisation optimale du processeur.
Votre machine va chauffer un petit peu car le processeur va être utilisé à prêt de 100%, mais le traitement va être bien plus rapide (7 minutes 49 secondes sur ma machine, soit un gain de 37%).
Si ma machine disposait de 4 ou 8 coeurs, ce qui est de plus en plus courant, le gain aurait été bien plus important.
Si vous avez encore plus efficace, je suis preneur.
Merci Linux !
Ne serait il pas plus rapide d’exécuter le tri, merge & le dé-duplique en tache de fond pour chaque fichier découpé ?
Du genre :
split -l 1000000 urls.txt urls.split.
for file in ls urls.split.*
do
sort $file | uniq > urls.sorted.txt.3 &
done
Mmm…
Pour faire le merge tu es obligé d’avoir tous les fichiers trié.
Mais faire les uniq dans la boucle ça se tente, pourquoi pas.
Je viens de tester, c’est moins efficace (10 minutes 12 secondes).
Je n’ai pas de Linux sous la main mais je crois qu’il existe une commande ‘parallel’.
Par ex. :
cat fichier.txt | parallel –pipe –files sort | parallel –pipe uniq > fichier.dedup.txt
travailler avec plusieurs threads ne veut pas dire travailler avec plusieurs cores…
Le vocabulaire utilisé n’est peut-être pas le bon, mais en l’occurrence, on travaille bien sur plusieurs cores.
Non ?
Tout a fait mais dans le cas d’un CPU « multi » cores, c’est l’OS qui distribue les threads sur les cores. Non ?
non, cela n’a rien à voir.
bien que cela ne soit pas sur linux, mais sur OSX, tu peux voir ici une explication : http://www.tempel.org/RB/MultiProcessing
par contre, peut-être y-a-t-il des tools en ligne de commande sous linux qui soit construit en multi-proc, tu dois le savoir en regardant l’implémentation. Par contre, tu ne divisera pas le temps par le nombre de processeurs. La synchronisation des process te faisant perdre ce que tu gagnes par ailleurs. Donc, il faut y aller doucement..
aller regarder de ce côté … peut-être http://sortbenchmark.org/
J’aimerais tant avoir ne serait-ce que 4 coeurs sur ma bécane, ça me changerait la vie!
C’est clair, heureusement que Linux existe sinon on irait pas bien loin…