Reputation: 2625
I have this script below that will be daemonized and triggered possibly hundreds if not thousands of times by different users.
The script uses inotifywait
to watch a folder for an upload and then move the uploaded file to its final destination for presentation, after rotating (backup/move) previous uploads. The code will be run against different upload folders that are created on the fly.
#!/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
What can I do to optimize it? Or should it be rewritten a faster programming language? Also, how can I test scripts under a certain amount of load?
Upvotes: 1
Views: 427
Reputation: 754570
You should avoid moving so many files around, by putting new files in new directories and leaving old files in old directories alone. You may need to reverse your presentation logic, so the newest file (biggest number) is shown, instead of post1.png
every time. But you speed that up by making it do less — and you make it do less by making it leave what's already there well alone.
If something is not fast enough, one of the best ways of speeding it up is to take a step back and look at the algorithms, and see whether there is a fundamentally faster algorithm that you can use. If you're already using the optimal algorithm, then you look at the details of how to speed that up, but you can sometimes get orders of magnitude improvement by revisiting the algorithm, where tweaking may get you a mere doubling of the speed.
Upvotes: 1
Reputation: 212454
This does not give identical behavior, but it avoids sorting:
#!/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
If you keep track of the highest number stored to $s3
, you can avoid the first
loop. Doing so is slightly more fragile if other processes are creating files
in $s3
, but in that case you have a race condition even in this simplistic solution.
It would be a lot simpler to not rename the files, but put the first file uploaded in
$s3/1
, and the next in $s3/2
. In that case the script can be written:
#!/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
Upvotes: 1
Reputation: 785631
You can refactor your script like this:
!/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")
Upvotes: 0