xargsを使って簡単に並列処理をする方法

この記事はPepabo Advent Calendar 2015の20日目の記事です。

先日とある案件で約400万個の画像データを別のサーバーにAPI経由でインポートする必要がありました。最初は単純に直列で実行してたのですが、終了予想を調べたら約20日かかる事になりあまりに遅すぎる!!と悩んでいた所、「並列処理で実行すればいいよ」というアドバイスを頂きました。いろいろ調べて試した結果、xargsで並列処理をするのが一番簡単かつ使いやすかったので使い方をまとめます。

サンプルスクリプト

現在時刻を表示した後に1秒間sleepします。

<?php

// 画像1件をインポートした体とする
echo date('Y-m-d H:i:s') . "\n\r";
sleep(1);

これをxargsコマンドを利用して10回直列実行すると下記の通り10秒かかります。これは想定通りです。

# for i in {1..10}; do echo $i ; done | xargs -n 1 php import.php
2015-12-19 01:01:22
2015-12-19 01:01:23
2015-12-19 01:01:24
2015-12-19 01:01:25
2015-12-19 01:01:26
2015-12-19 01:01:27
2015-12-19 01:01:28
2015-12-19 01:01:29
2015-12-19 01:01:30
2015-12-19 01:01:31

-n は引数の数を指定します。

並列処理の実行方法

-P #{1度に実行したい最大プロセス数}を指定するだけです。
下記では10回の処理を5並列で実行することにより2秒で処理を終えています。倍速に!!
並列で起動させるプロセス数によっては倍速やそれ以上の速度で処理ができます。

# for i in {1..10}; do echo $i ; done | xargs -P 5 -n 1 php import.php
2015-12-19 00:59:29
2015-12-19 00:59:29
2015-12-19 00:59:29
2015-12-19 00:59:29
2015-12-19 00:59:29
2015-12-19 00:59:30
2015-12-19 00:59:30
2015-12-19 00:59:30
2015-12-19 00:59:30
2015-12-19 00:59:30

実行中のプロセスの様子を見ると下記の通り5プロセスで処理していることが分かります。

# ps aux | grep php
root      9716  0.0  0.1   6336   628 pts/0    S+   16:10   0:00 xargs -P 5 -n 1 php import.php
root      9717  1.0  1.2 115728  7348 pts/0    S+   16:10   0:00 php import.php 1
root      9718  0.0  1.2 115728  7344 pts/0    S+   16:10   0:00 php import.php 2
root      9719  1.0  1.2 115728  7344 pts/0    S+   16:10   0:00 php import.php 3
root      9720  0.0  1.2 115728  7344 pts/0    S+   16:10   0:00 php import.php 4
root      9721  0.0  1.2 115728  7340 pts/0    S+   16:10   0:00 php import.php 5

引数も操作できる

php import.php --start=1

とコマンドラインのオプションに合わせて引数を渡したい場合は下記のように-Iオプションで標準入力を中身を変数に格納し、それをコマンドラインの好きな場所で指定するだけです。

for i in {1..10}; do echo $i ; done | xargs -P 5 -I no php import.php --start=no
root      9979  0.0  0.7 101576  4324 pts/0    R+   16:30   0:00 php import.php --start=6
root      9980  0.0  0.6 101576  4140 pts/0    R+   16:30   0:00 php import.php --start=7
root      9981  0.0  0.7 109792  4612 pts/0    R+   16:30   0:00 php import.php --start=8
root      9982  0.0  0.7 101576  4456 pts/0    R+   16:30   0:00 php import.php --start=9
root      9983  0.0  0.5  67156  3440 pts/0    R+   16:30   0:00 php import.php --start=10

最後に

地味なお話でしたがいかがでしたでしょうか。恐らく普段のWebアプリケーション開発では使うことは無いかと思いますが、サーバー移転やデータ連携の都合で大量データを処理する必要がある場合は、並列処理を利用することで高速化を図ることが出来ます。もちろん各言語別で並列処理を実装する事もできますが、個人的にはシンプルな実装、メモリー使用量の考慮、使い勝手を考慮してxargs方式がお気に入りでした。もし機会があれば使ってみてください。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする