2012-10-30 2 views
1

J'ai ce script ci-dessous qui sera démonisé et déclenché peut-être des centaines sinon des milliers de fois par différents utilisateurs.Optimisation du script bash

Le script utilise inotifywait pour regarder un dossier pour un téléchargement, puis déplace le fichier téléchargé vers sa destination finale pour la présentation, après la rotation (sauvegarde/déplacement) des téléchargements précédents. Le code sera exécuté sur différents dossiers de téléchargement créés à la volée.

#!/bin/bash 

db="$VAR1"/path/to/upload/folder/ 
s3="$VAR2"/path/to/remote/folder 

inotifywait -m -r -e attrib "$db" | 
while read dir ev file; 
do 

     for dirnum in $(cd "$s3"; ls */*.png | sed 's%/.*%%' | sort -nr) 
     do 
       next=$(($dirnum + 1));      
       mv "$s3/$dirnum/post$dirnum.png" "$s3/$next/post$next.png"; 
     done 

     mv "$db"/"$file" "$s3"/1/post1.png 

done 

Que puis-je faire pour l'optimiser? Ou devrait-il être réécrit un langage de programmation plus rapide? Aussi, comment puis-je tester des scripts sous une certaine quantité de charge?

+0

Si elle est assez rapide, elle n'a pas besoin d'être réécrite. Vous pouvez le tester en y jetant des fichiers. Une optimisation évidente est de garder une trace du nombre dans chaque répertoire (WTF est un "dossier"?) Au lieu de le calculer à chaque fois. –

+0

Relatif à, mais une extension de, [Quelle est la bonne façon de boucle ce?] (Http://stackoverflow.com/questions/13097606/whats-the-correct-way-to-loop-this/) –

Répondre

1

Cela ne donne pas un comportement identique, mais il évite le tri:

#!/bin/bash 

db="$VAR1"/path/to/upload/folder/ 
s3="$VAR2"/path/to/remote/folder 

inotifywait -m -r -e attrib "$db" | 
while read dir ev file; 
do 
    dirnum=1 
    while test -e "$s3/$dirnum"; do : $((dirnum += 1)); done 
    while test $dirnum -gt 0; do 
     next=$((dirnum + 1));  
     mkdir -p $s3/$next     
     mv "$s3/$dirnum/post$dirnum.png" "$s3/$next/post$next.png" 
     : $((dirnum -= 1)) 
    done 
    mv "$db/$file" "$s3"/1/post1.png 
done 

Si vous garder une trace du nombre le plus élevé enregistré à $s3, vous pouvez éviter la première boucle . Cela est légèrement plus fragile si d'autres processus créent des fichiers dans $s3, mais dans ce cas vous avez une condition de concurrence même dans cette solution simpliste. Il serait beaucoup plus simple de ne pas renommer les fichiers, mais mettre le premier fichier téléchargé en $s3/1, et le prochain en $s3/2. Dans ce cas, le script peut être écrit:

#!/bin/bash 

db="$VAR1"/path/to/upload/folder/ 
s3="$VAR2"/path/to/remote/folder 
dirnum=1 
while test -e "$s3/$dirnum"; do : $((dirnum += 1)); done 
inotifywait -m -r -e attrib "$db" | 
while read dir ev file; 
do 
    mkdir -p "$s3"/$dirnum 
    mv "$db/$file" "$s3"/$dirnum/post$dirnum.png 
    : $((dirnum += 1)) 
done 
+0

le premier le script est super plus rapide que mon original, et il fait ce qu'il est censé faire, déplacer le post plus ancien vers le DIRECTORY numéroté suivant. note: le seul processus de création de fichiers dans $ S3 est ce script .. il y aura un $ S4, $ S5 etc. mais où dans le script il est dit de commencer l'itération au répertoire $ S3/101? le second script est intrigant mais il place le post uploadé dans un répertoire $ S3/107 puis le prochain upload en $ S3/108 le dernier upload doit toujours être en $ S3/1 et le suivant en $ S3/2. .. merci pour les leçons d'optimisation. Mal part avec le premier script que vous avez posté! – sirvon

+1

La première boucle interne incrémente dirnum jusqu'au premier répertoire non existant (apparemment 101 dans votre cas). –

0

Vous pouvez factoriser votre script comme ceci:

!/bin/bash 

db="$VAR1"/path/to/upload/folder/ 
s3="$VAR2"/path/to/remote/folder 

while read dir ev file 
do 
    while read dirnum 
    do 
     next=$(($dirnum + 1)) 
     mv "$s3/$dirnum/post$dirnum.png" "$s3/$next/post$next.png" 
    done < <(find "$s3" -depth 2 -name "*.png" -exec dirname {} \; | sort -unr) 

    mv "$db"/"$file" "$s3"/1/post1.png 

done < <(inotifywait -m -r -e attrib "$db") 
1

Vous devez éviter de déplacer autant de fichiers autour, en mettant de nouveaux fichiers dans de nouveaux répertoires et en laissant les anciens fichiers dans les anciens répertoires seuls. Vous devrez peut-être inverser votre logique de présentation, de sorte que le fichier le plus récent (le plus grand nombre) est affiché, au lieu de post1.png à chaque fois. Mais vous accélérez cela en faisant en faire moins - et vous le faites moins en le faisant partir ce qui est déjà là bien seul. Si quelque chose n'est pas assez rapide, l'une des meilleures façons de l'accélérer est de prendre du recul et de regarder les algorithmes, et de voir s'il existe un algorithme fondamentalement plus rapide que vous pouvez utiliser. Si vous utilisez déjà l'algorithme optimal, alors vous regardez les détails de la façon d'accélérer cela, mais vous pouvez parfois obtenir des améliorations d'ordre de grandeur en revisitant l'algorithme, où le réglage peut vous faire doubler la vitesse.

+0

ty pour la compréhension. déplacer les choses est le goulot d'étranglement. Je suis maintenant obligé de faire l'avant aussi dynamique que le dos! J'aime le progrès. Je n'ai pas réalisé que je suis en train de concevoir un algorithme. mes yeux sont ouverts. – sirvon