@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

Node学園 31時限目でLTしました #tng31

Node.jsの並列プログラミングについて話してきました。 大量のhtmlファイルをパースする処理を、 child_process.forkを使って複数プロセスへ分散した話をしました。 また、worker_threadsを試した話をしました。 めっちゃフィードバックがもらえて楽しかったです。

speakerdeck.com

フィードバック

「並列数を増やした時のボトルネックがわかりません」と発表したところ、 楽しんでいただけだようで、たくさんのアイデアをいただきました。

週末の間、ボトルネックとして成り立つ確率と、検証方法を考えてみました。 一通り検証する予定です*1

ボトルネックファイル仮説

いずれか(複数の可能性もある)のhtmlファイルが巨大であるなどの理由で時間が掛かっていて、ボトルネックになっているのでは?

1ファイル辺りの処理時間は数十ms程度なので、多少ばらついても秒単位のボトルネックにならないようにも思えます。 しかし、現在はラウンドロビンでタスクをサブプロセスに割り振っています。 何回起動しても、同じプロセスに同じタスクが割り振られます。 1ファイルで秒単位のばらつきが出ないとしても、タスク群としては出る可能性があります。

プロセス単位で、終了までの時間を出力すれば検証できそうです。

メモリ仮説

プロセス数が増えて消費メモリが大きくなるがボトルネックになっているのでは?

現代では36プロセスが多すぎるとは思えません。 また、EC2はデフォルトでは、swapファイルの割当がなく、メモリが足りなくなると即エラーになりOOM killerが飛んできます。 今の所、OOM killerを観測していません。ただ、すべてのサブプロセスの状態を監視しているわけではないので、知らずに死んでいる可能性はあります。 この場合も、出力データが壊れても、処理時間には影響がなさそうです。

実行時の消費メモリを観測すれば検証できそうです。

物理コア仮説

AWS EC2で試したので、Virtual CPUが36コアだとしても物理CPUが10コアしか無いため、実際は36並列まで伸びないのでは?

クラウド環境にありそうな話です。 ただし、グラフがなめらかな点が気になります。 コア数が足りなくなればそこから水平になると予想できますが、公開したグラフで25コアまでは微減です。 また、機械学習勢の人たちは、僕より早くマルチコア環境を試していそうなので、そういう事実があれば炎上していそうなものです。

物理 CPU、CPU コア、および論理 CPU の数を確認する - Red Hat Customer Portal のコマンドで物理CPU数・コア数と論理コア数を確認すれば何かわかるかもしれません。

共有ログ仮説

書いているログ・ファイルが一つであれば、書き込みがボトルネックになっているのでは?

実際ログは一つのファイルなのでありそうです。 発表中に説明していませんが、重複ログを書きこまない機能があります。 ログを書くかどうかはログの状態によってばらつきます。 この機能が影響しているにしては、グラフがきれいすぎる気もします。

ログ書き込みを止めて計測すれば検証できそうです。

その他

GNU Parallel使うといいのでは?

元々Go lang*2Ruby*3辺りに移植して、多言語の実行環境と性能比較したいとは思っていました。 1から違う言語で書き直すのは大変なので、Node.jsのまま入出力だけ修正して、GNU Parallelを使うというのは、 より短い時間で試せるいいアイデアです。

その他の感想

参考に次の記事を挙げました。 何人か「この記事を参考にしてスクレイピングに挑戦しています」と言ってくれる人がいました。 書いてよかったです。

qiita.com

*1:確率が低くても否定材料を集めておくことは、デバッグ最速理論的に大事なのです

*2:この手の並列はgo langのGoroutinesが強いイメージなので、実際に試してみたいです。

*3:rubexを使うとGILを超えて並列化できるという触れ込みなので実際に試してみたいです。