xargs --max-procs を使用するときにプロセスの開始時に視差を置くには?

xargs --max-procs を使用するときにプロセスの開始時に視差を置くには?

処理するファイルが数百個ありますが、一度に10個のプロセスしか実行したいと思います。 「doSomething」プロセスを完了するのに20秒かかったとします。以下はうまくいきますが、ほぼ同時に10のプロセスを開始します。約20秒後、最初の10セットが完了し、次の10セットがほぼ同時に開始され、シリーズが繰り返されます。同時に開始せずに視差を置いて開始するにはどうすればよいですか?

find ./someFiles* | xargs --max-args=1 --max-procs=10 ./doSomething

プロセスがほぼ同時に10秒ではなく、少なくとも2秒間隔で開始されることを望みます。

答え1

これは、複数のインスタンスが同時に起動したときにディスク/ネットワークまたは他のリソース使用量が急増するのを防ぐために行われます。少なくとも最初のN個については、X秒の固定間隔が必要です。

簡単な回避策は、追加の値を挿入してxargsパラメータを延期することです。このように:

find . -type f -print0 |
xargs -0 -n1 -P1 sh -c 'sleep 2; printf "%s\0" "$0"' |
xargs -0 -n1 -P4 sh do_something.sh

上ではN=4、間隔は2秒です。最初のN個のパラメータについては間隔が維持されます。その後、いくつかの実行がほぼ終了した場合は、時間に合わせてより近い実行を開始できます。これはまさにそれに対する要求です。コメント

また、実行時間も短くなく、数秒以上になると仮定しています。次回実行してもスパイクが発生する場合は、遅延を少し高く設定することもできます。最初は大きなボトルネックを防ぎます。


テスト

以下はいくつかの基本的なテストです。スクリプトdo_something.shの処理にはランダムに10〜20秒かかります。

> cat do_something.sh 
printf "%s START processing %s\n" "$(date +"%H:%M:%S")" "$1"
sleep $(shuf -i10-20 -n1)
printf "%s END processing %s\n" "$(date +"%H:%M:%S")" "$1"

> touch file{1..10}

> find . -type f -name 'file*' -print0 |
> xargs -0 -n1 -P1 sh -c 'sleep 2; printf "%s\0" "$0"' |
> xargs -0 -n1 -P4 sh do_something.sh
02:03:22 START processing ./file6
02:03:24 START processing ./file9
02:03:26 START processing ./file8
02:03:28 START processing ./file2
02:03:38 END processing ./file8
02:03:38 START processing ./file7
02:03:40 END processing ./file6
02:03:40 START processing ./file1
02:03:41 END processing ./file9
02:03:41 START processing ./file3
02:03:45 END processing ./file2
02:03:45 START processing ./file4
02:03:55 END processing ./file3
02:03:55 END processing ./file7
02:03:55 START processing ./file10
02:03:55 START processing ./file5
02:04:00 END processing ./file1
02:04:02 END processing ./file4
02:04:05 END processing ./file10
02:04:13 END processing ./file5

答え2

一種のシェルスクリプトであると仮定し、次を上に置きます。

export MYPID=$$
(
    flock 9
    mkdir -p .started-pids
    find .started-pids/ -type f ! -newermt '-2 seconds' -delete
    n=`find .started-pids/ -type f | wc -l`
    sleep $n
    sleep $n
    touch .started-pids/$MYPID
) 9> .lockfile

そうではないかなり正確さ - 時々少し遅れるもっと必要以上に、しかしそれ以上のスパイクが発生しないようにしてください。

もちろん、ロックファイルとpidカウントディレクトリ名を必要に応じて変更してください。

関連情報