この記事は 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方式がお気に入りでした。もし機会があれば使ってみてください。