2022年9月25日日曜日

Node.jsのワーカースレッドを使ってみた

 え、今更?

はい。めっちゃ今更です。存在は知っていたし使い方も知っていたんですが、今まで使う機会がなくて使っていませんでした。

で、このたび必要に迫られたので使ってみた・・・というわけではなく、そろそろただの知識だけじゃなくて実際に使ってみないとアカンよなぁという感じで使ってみただけです。使ってみたというより動かしてみたと言ったほうが正確かもしれません。

使い方に関しては検索すればいくらでも出てくるので、ここでは省略します。なにか参考になるものがほしい方はとりあえず公式ページをどうぞ。

使ってみた感想

最初に感じたのは、スレッドというよりプロセスに近いなぁという印象。内部のアーキテクチャーはともかく、使い勝手はかなりプロセスに近いのでC言語とかのスレッドのつもりで使おうとすると首をひねります。

具体的には、

  • スレッド間でグローバル変数を共有できない
  • オブジェクト・メモリーの共有は(基本的に)できない
  • ワーカースレッド内でprocess.exit()をコールすると、プロセス全体ではなく実行中のスレッドのみ終了する

といった感じ。

最初の2つについては、スレッドセーフとかアトミック操作のような低レイヤーのことを意識せずに設計した結果なのでしょうか。

グローバル変数はスレッドごとに独立しているので、グローバル変数を使ってスレッド間で情報共有はできません。逆にいえば、他のスレッドとの競合を気にすることなく自スレッド専用リソースとして使えます。

スレッド間でのメモリーの共有も原則できません。どうしても共有したい場合はSharedArrayBufferのように特別に用意された専用のオブジェクトを使う必要があります。もちろんその場合はスレッドセーフとかアトミック操作を意識する必要があるので、Atomicsなどを使って慎重に組み上げましょう。ちょっと間違えるとなかなか再現しないめんどいバグが・・・

process.exit() に関しては・・・うん。しゃーない

使いどころ

理屈でいえば、ウェブサーバーを走らせながら裏でCPUをぶん回すような処理が必要な場合に有効なんですが、一般的なウェブアプリケーションではあまりそういう状況はないんですよね。待ち時間のほとんどがDBとかのI/Oだし、CPU以外のI/Oで待たされるようなケースでは普通に非同期処理を使えばいいので。

無理やり使いどころを探すなら機械学習APIとかでしょうか。学習APIに学習データを渡して裏でモデルを構築するとか、逆に結果取得APIに入力値を渡して裏で計算して結果を取り出すとか。Node.jsで全部やる必要があるかと言われるとわかりません

ウェブサーバー以外の用途だと何があるかな。スケジューラーのBreeではタスクの起動にワーカースレッドを使っていますね。「ライブラリーを使う人のスキルレベルは様々なので、CPU消費しまくりとか同期I/O使いまくりとかの行儀の悪いタスクがあった場合でもできるだけ正確にタスクを起動したい」という意図を汲み取ると、確かにワーカースレッドは適切かもしれません。

0 件のコメント:

コメントを投稿