2015年4月7日にリリースされたEmbulk 0.6.0から、Executorをプラグインで差し替え可能になりました。このニュースリリースの中に、
The built-in executor plugin is LocalExecutorPlugin that runs tasks using multiple threads. It has a shared thread pool and schedules tasks at most (number of available CPU cores) * 2 tasks in parallel. Number of threads is configurable using max_threads system parameter.
http://www.embulk.org/docs/release/release-0.6.0.html:Release 0.6.0 — Embulk 0.6 documentation
とあったので、
exec: type: local max_threads: 1
とconfigファイルで指定すればいいのか!と思ってやってみたら、さっぱりスレッド数が制限されず、さんざん悩んでしまいました*1。
で、結論としては、以下のように-Jオプション(JRubyでJVMパラメータを渡すためのオプション)を使って、embulk.max_threadsに値を設定することで、最大スレッド数が有効になりました。
% embulk -J-Dembulk.max_threads=1 run config.yml > result.txt
file inputプラグインの場合、1スレッドで1ファイルを読むようなので、以下の例ではresult.txtをtail -fとかで見てみると、確かに1スレッドで動作しているのがわかります。
こちら、今回も開発者の古橋さんにtwitterで教えてもらいました。いつもありがとうございます。なお、古橋さんによると、LocalThreadExecutorは、プロセスにつき1個あるグローバルなスレッドプールを直接使う実装になっているとのことです。そのため、0.6.0以前から最大スレッド数の指定自体はできたようです。あとになって見つけたのですが、以下のような記事もありました。
Embulkでタスクを処理するスレッドの数を変更する方法 - Qiita
古橋さんの解説
僕が最初に試したような感じで、プラグインの設定で最大スレッド数を指定できた方が自然な気がしますが、以下の理由で難しいそうです。
@muziyoshiz LocalExecutorPluginのmax_threadsは、普通のconfigではなく、system config扱いになっています。コマンドラインの先頭に -J-Dembulk.max_threads=1 と指定するとどうでしょう?
— FURUHASHI Sadayuki (@frsyuki) 2015, 5月 7
@muziyoshiz LocalThreadExecutorは、プロセスにつき1個あるグローバルなスレッドプールを直接使う実装になっています。そういうグローバルな設定は、system configになっています。
— FURUHASHI Sadayuki (@frsyuki) 2015, 5月 7
@muziyoshiz これは1プログラムで複数のバルクロードを並列で実行するような(embulkを組み込んで使う)アプリケーション向けなのです。コマンドラインで使う場合は、1プロセスで1バルクロードなので、改善の余地ありなのです。
— FURUHASHI Sadayuki (@frsyuki) 2015, 5月 7
@muziyoshiz これを改善するには、2段階にする必要があるのです。つまり、グローバルなスレッドプールの最大スレッド数とGT、1バルクロードが使う最大スレッド数LT(LT < GT)を別々に設定できるようにすれば解決するハズです。
— FURUHASHI Sadayuki (@frsyuki) 2015, 5月 7